ConcurrentHashMap::computeIfAbsent and synchronized
Doug Lea
dl at cs.oswego.edu
Fri Jan 20 12:51:17 UTC 2023
Updates to ConcurrentHashMap to avoid builtin synchronization are on the
todo list. As you've noticed, using a ReentrantLock per node would add
unacceptable overhead, and would be especially unwelcome for the huge
number of non-loom usages. I have a few ideas in mind, but it will
surely be a while until arriving at a replacement good enough to release.
-Doug
On 1/20/23 02:40, Dr Heinz M. Kabutz wrote:
>
> Hi Mika,
>
> I was thinking about that yesterday. Since CHM gives a guarantee that
> the compute() functions are called atomically, it might be worth
> looking at the implications of moving (back) to ReentrantLock.
> However, that would also mean that we need to allocate a lot of
> ReentrantLock instances, and those are 40 bytes per lock. Here is a
> demo that shows the issue:
>
> import java.util.Map; import java.util.concurrent.CancellationException; import java.util.concurrent.ConcurrentHashMap; public class CHMPinning {
> public static void main(String... args)throws InterruptedException {
> Map<Integer, Integer> map =new ConcurrentHashMap<>(); for (int i =0; i <1_000; i++) {
> int finalI = i; Thread.startVirtualThread(() ->
> map.computeIfAbsent(finalI %3, key -> {
> try {
> Thread.sleep(2_000); }catch (InterruptedException e) {
> throw new CancellationException("interrupted"); }
> return finalI; })); }
> long time = System.nanoTime(); try {
> Thread.startVirtualThread(() ->
> System.out.println(
> "Hi, I'm an innocent virtual thread"))
> .join(); }finally {
> time = System.nanoTime() - time; System.out.printf("time = %dms%n", (time /1_000_000)); }
> System.out.println("map = " + map); }
> }
>
> Output is something like:
>
> Hi, I'm an innocent virtual thread
> time = 2002ms
> map = {0=0, 1=7, 2=2}
>
> IMHO, I would not like to see the CHM memory usage increase by 40 x #
> nodes bytes to cater for an edge case of the compute() function taking
> a bit longer.
>
>
> Regards
>
> Heinz
> --
> Dr Heinz M. Kabutz (PhD CompSci)
> Author of "The Java™ Specialists' Newsletter" -www.javaspecialists.eu
> Java Champion -www.javachampions.org
> JavaOne Rock Star Speaker
> Tel: +30 69 75 595 262
> Skype: kabutz
> On 2023/01/20 01:22, mikmoila wrote:
>> Hi.
>>
>> As often mentioned in this mailing-list a feedback about
>> preview/incubator features is appreciated, so here's one:
>>
>> I was experimenting with a caching system utilising ConcurrentHashMap
>> as cache store and Structured Concurrency API for refreshing the
>> entries from multiple sources ( StructuredTaskScope.ShutdownOnSuccess
>> ). The idea was to make http-requests for getting the fresh values
>> but the first implementation simply uses UUID::randomUUID for
>> simulating that.
>> I noticed that the programs halts In a test case where "N" concurrent
>> calls (where "N" >= number of cpu cores) running on virtual threads
>> end-up calling the ConcurrentHashMap::computeIfAbsent for the same
>> (non-existing) key.
>>
>> "-Djdk.tracePinnedThreads=full" reveals that there is a pinned
>> carrier thread:
>> java.base/java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1708)
>> <== monitors:1
>>
>> The documentation (
>> https://docs.oracle.com/en/java/javase/19/docs/api/java.base/java/util/concurrent/ConcurrentHashMap.html#computeIfAbsent(K,java.util.function.Function)
>> ) says:
>>
>> "Some attempted update operations on this map by other threads may
>> be blocked while computation is in progress, so the computation
>> should be short and simple."
>>
>> This is clear but I still found it as a surprise that it uses
>> synchronized instead of "virtual-thread friendly" constructs.
>>
>> If needed I can post a small demo program.
>>
>> JDK used is latest OpenJDK-19 GA, OS is Windows:
>> openjdk version "19.0.2" 2023-01-17
>> OpenJDK Runtime Environment (build 19.0.2+7-44)
>> OpenJDK 64-Bit Server VM (build 19.0.2+7-44, mixed mode, sharing)
>>
>> Best Regards,
>> Mika
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.openjdk.org/pipermail/loom-dev/attachments/20230120/89ca977e/attachment-0001.htm>
More information about the loom-dev
mailing list