collections

ConcurrentHashMap: Segmentation vs CAS Locking

🔹 ConcurrentHashMap Internal Locking (Deep Dive, Interview-Ready)

To truly impress an interviewer, you must be able to explain exactly how ConcurrentHashMap (CHM) achieves its incredible throughput, and specifically, how its internal architecture completely changed between Java 7 and Java 8.


📌 1. The Java 7 Era: Segment-Based Locking

In Java 7, ConcurrentHashMap used a technique called Lock Striping.

Instead of locking the entire map (like HashTable), the map was divided into an array of Segments (default size: 16).

  • Each segment acted like its own independent, mini HashTable backed by a ReentrantLock.
  • The Benefit: Up to 16 threads could write to the map at the exact same time, provided their keys hashed to different segments.
  • The Drawback: Creating 16 ReentrantLock objects and managing these segments consumed a massive amount of memory, even if the map was empty. Furthermore, if you needed more than 16 concurrent writers, threads would start blocking each other.

📌 2. The Java 8 Revolution: Node-Level CAS Locking

In Java 8, Doug Lea completely scrapped the Segment approach. The new ConcurrentHashMap was redesigned to match the bucket-array structure of the new Java 8 HashMap (with linked lists and Red-Black Trees), but augmented for concurrency.

The new approach relies heavily on CAS (Compare-And-Swap) and synchronized blocks at the node level.

🔸 Scenario A: Inserting into an Empty Bucket (Lock-Free!)

If a thread calculates the hash and finds that the array bucket is currently null (empty), it does not acquire a lock. Instead, it uses an atomic hardware-level instruction called Unsafe.compareAndSwapObject().

  • CAS Logic: "Check if the bucket is STILL null. If yes, insert my node. If no, someone else just beat me to it, so fail and try again."
  • Result: Zero blocking, maximum speed.

🔸 Scenario B: Inserting into an Occupied Bucket (Node Lock)

If the bucket already has a node (a collision), CAS cannot be used safely to manage the linked list or tree. Instead, the thread applies a standard synchronized block, but only on the very first node (head) of that specific bucket.

  • Result: Only threads trying to write to the exact same bucket will block. A thread writing to Bucket 5 will never block a thread writing to Bucket 12. This allows potentially thousands of concurrent writers.

📌 3. Why Nulls are strictly forbidden

Unlike HashMap, CHM strictly prohibits null keys and null values. Why? To prevent the ambiguous "Missing vs Null" problem in a concurrent environment.

In a single-threaded environment:

Object value = map.get("key"); if (value == null) { if (map.containsKey("key")) { // The value is explicitly null } else { // The key doesn't exist } }

In a multi-threaded environment, this is fundamentally broken. Between the get() and the containsKey() checks, another thread could insert or delete the key. The state is ambiguous. To prevent this race condition entirely, null values are banned, meaning if get() returns null, it unequivocally means the key is missing.


📌 4. Fail-Safe Iteration (Weakly Consistent)

Standard maps throw a ConcurrentModificationException if modified during iteration. ConcurrentHashMap provides a weakly consistent iterator.

  • It will traverse elements as they existed at the moment the iterator was created.
  • It may or may not reflect updates made after the iterator was created.
  • It is guaranteed never to throw ConcurrentModificationException.

🔥 Interview Gold Statement

"In Java 7, ConcurrentHashMap relied on Lock Striping, dividing the map into 16 Segments backed by ReentrantLocks. While better than HashTable, it had heavy memory overhead and an artificial concurrency limit. In Java 8, it was completely redesigned to use Node-level synchronization and hardware-level CAS (Compare-And-Swap) operations. For empty buckets, it inserts nodes lock-free via CAS. For collisions, it synchronizes only on the head node of that specific bucket array index. This granular locking allows nearly infinite scalability without the memory bloat of segments."


âš¡ Final Verdict

  • ✅ Java 8 ConcurrentHashMap is a masterclass in highly granular locking, using CAS for lock-free insertions and node-level synchronized blocks for collision handling.
ConcurrentHashMap: Segmentation vs CAS Locking | DevExCode