ConcurrentHashMap
KOTLIN › Concurrency
ConcurrentHashMap in depth: lock-free reads, CAS + bin locks, atomic compound ops, and its traps.
ConcurrentHashMap is the JMM's machinery packaged as a map: reads never lock, writes synchronise per bin, and putting a value happens-before retrieving it. Interviewers use it two ways: can you explain HOW it achieves thread safety without a global lock, and do you know its contract well enough to avoid the traps: check-then-act on a 'thread-safe' map, side effects inside compute functions, and trusting size() or iterators to be exact under concurrency. It is the default answer for shared caches in a live-coding round, so know why, and know what it still does not solve.
What this covers
- The guarantee: fully concurrent reads and high-throughput writes; the docs promise that actions before placing an object happen-before actions after retrieving it (the JMM edge is baked in)
- Write path (Java 8+): CAS installs the first node of an empty bin; collisions lock only that bin's head node with synchronized; long bins treeify; no global lock, and the old segment/striping design is gone
- Read path: get() never locks; node value/next fields are volatile, so traversal sees safely published entries
- Resize is cooperative: writer threads that notice a resize help transfer bins (ForwardingNode), while readers follow forwarding pointers and keep working
- Per-operation atomicity is NOT transaction-ness: get-then-put still races; use the atomic compound ops putIfAbsent, compute, computeIfAbsent, computeIfPresent, merge, and replace(key, expected, new)
- compute-function rules: keep the lambda short and side-effect-free, and never touch the same map inside it; recursive or re-entrant updates can throw IllegalStateException or deadlock on the bin lock
- Weak consistency: iterators never throw ConcurrentModificationException and may or may not reflect concurrent updates; size() and isEmpty() are estimates maintained by striped counters
- No null keys or values (absent vs stored-null must stay unambiguous); extras worth knowing: newKeySet() as a concurrent set, bulk parallel forEach/search/reduce, and Kotlin's ConcurrentMap.getOrPut riding on putIfAbsent
Study this topic
- ConcurrentHashMap explained: the guided lesson
- 14 practice quiz questions
- 9 revision flashcards
- ConcurrentHashMap interview questions and answers