Concurrency is hard. Java has no exception. In this post and possible future posts, I will record traps and pitfalls, I experienced or heard, in Java.
Nested write in
ConcurrentHashMap.compute could deadlock
ConcurrentHashMap uses bucket level lock in write operations (e.g.
compute) to protect bucket nodes. If nested writing key falls to the same bucket
ConcurrentHashMap.compute is serving, then it deadlocks. The javadoc of
ConcurrentHashMap.compute and its siblings warn this.
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, and must not attempt to update any other mappings of this Map.
I encountered this once in production code and the “update” is shadowed by
There are others encountering this.
- JDK-8062841: ConcurrentHashMap.computeIfAbsent stuck in an endless loop
- Deadlock due to ConcurrentHashMap.compute in PrometheusMeterRegistry
- Avoid Recursion in ConcurrentHashMap.computeIfAbsent()
CompletableFuture.complete will run non-async computations if it completes the future
Actions supplied for dependent completions of non-async methods may be performed by the thread that completes the current CompletableFuture, or by any other caller of a completion method.
I think it is not a good design, it makes
CompletableFuture.complete vulnerable to
CompletableFuture.handle. I did see code in production utilize this subtlety to build strong happen-before relation between
when and code after