ConcurrentHashMap::computeIfAbsent and synchronized
thurston N
thurston.nomagicsoftware at gmail.com
Sat Jan 21 22:07:56 UTC 2023
Just spitballing,
there's already a ReservationNode type, adding a ReentrantLock instance
variable to it should address the overhead issue (since each
ReservationNode is very short-lived, only temporarily in the #table)
although the else branch in computeIfAbsent wouldn't be pretty and would
require instance of checks
-T
On Fri, Jan 20, 2023 at 4:51 AM Doug Lea <dl at cs.oswego.edu> wrote:
> 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/20230121/adc1193f/attachment-0001.htm>
More information about the loom-dev
mailing list