ConcurrentHashMap Evolution in Java

ConcurrentHashMap is a high-performance, thread-safe Map implementation from the java.util.concurrent package.

Evolution in Jdk7 and Jdk8

JDK 7: Segmented Locking

In JDK 7, ConcurrentHashMap adopted lock striping (a form of segmented locking).

public V put(K key, V value) {
    Segment<K,V> s;
    int hash = hash(key);
    int j = (hash >>> segmentShift) & segmentMask;
    s = ensureSegment(j);
    return s.put(key, hash, value, false);
}

JDK 8+: CAS + synchronized + Red-Black Trees

JDK 8 restructured ConcurrentHashMap.

final V putVal(K key, V value, boolean onlyIfAbsent) {
    int hash = spread(key.hashCode());
    for (Node<K,V>[] tab = table;;) {
        ...
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null)))
                break; // CAS avoids locking for empty bin
        } 
        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);//Help resize and treeify
        else {
            synchronized (f) { //Lock only first node of bin
                ...
            }
        }
    }
}

JDK 8 completely removed the Segment class. CAS + fine-grained synchronized blocks significantly improved performance. Treeification further improved lookup speed for highly-collided keys.

Resizing in JDK 7 vs JDK 8

JDK 7 Resizing

JDK 8 Resizing

else if ((fh = f.hash) == MOVED)
    tab = helpTransfer(tab, f); // Assist with resizing

In JDK8, if a thread sees that a bin is being resized, it doesn’t just wait. It actively helps with the resizing process, which reduces blocking and speeds things up.

Additional Enhancements in JDK 9 to JDK 21

While the core structure introduced in JDK 8 remains intact, newer JDKs have introduced several performance and usability improvements.

  1. Compact Memory Layout
  1. False Sharing Mitigation
  1. Optimized Tree Handling
  1. Enhanced Parallelism Support

In the future, Java will keep on optimizing ConcurrentHashMap.