Unlocking the Secrets of Java’s ConcurrentHashMap: From JDK 7 to JDK 8

This article provides a comprehensive, step‑by‑step analysis of Java's ConcurrentHashMap, covering its evolution from JDK 7’s segment‑lock design to JDK 8’s bucket‑level CAS and synchronized approach, complete with macro diagrams, microscopic source‑code walkthroughs, hash calculations, resizing mechanisms, and practical usage tips.

Programmer Null's Self-Cultivation
Programmer Null's Self-Cultivation
Programmer Null's Self-Cultivation
Unlocking the Secrets of Java’s ConcurrentHashMap: From JDK 7 to JDK 8

01 ConcurrentHashMap Overview

ConcurrentHashMap is the de‑facto standard container for high‑concurrency scenarios in Java. It replaces the non‑thread‑safe HashMap and the heavyweight HashTable, offering fine‑grained locking and lock‑free reads.

02 Macro View: Evolution Diagram

HashMap – non‑thread‑safe, uses an array of Entry objects with singly linked lists. In JDK 8 it adds a red‑black tree when a bucket’s list length reaches 8 and the table size is at least 64.

HashTable – early thread‑safe implementation that locks the entire table, leading to poor scalability.

ConcurrentHashMap – provides high‑performance thread safety. JDK 7 uses segmented locks ( Segment array) while JDK 8 removes segments and adopts a bucket‑level design with Node + linked list/red‑black tree + CAS + synchronized.

03 Microscopic View: Source Code Dissection

JDK 7 Implementation

final Segment<K,V>[] segments; // segment array
static final class Segment<K,V> extends ReentrantLock {
    transient volatile HashEntry<K,V>[] table; // per‑segment hash table
    // ...
}
static final class HashEntry<K,V> {
    final int hash;
    final K key;
    volatile V value; // volatile for visibility
    volatile HashEntry<K,V> next; // volatile pointer
    // ...
}

The default concurrency level is 16, creating 16 segments. Each segment’s capacity is calculated as initialCapacity / concurrencyLevel, rounded up to the nearest power of two.

int segmentCapacity = initialCapacity / concurrencyLevel;
segmentCapacity = roundUpToPowerOf2(segmentCapacity);
threshold = (int)(segmentCapacity * loadFactor); // default load factor 0.75

When the first entry is inserted, size reaches threshold and triggers a segment‑level resize.

JDK 8 Implementation

static final class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val; // volatile for visibility
    volatile Node<K,V> next; // volatile pointer
    // ...
}
static final class TreeBin<K,V> extends Node<K,V> {
    TreeNode<K,V> root; // red‑black tree root
    volatile TreeNode<K,V> first; // linked‑list head for iteration
    volatile Thread waiter; // for read‑write lock control
    // ...
}

Hash calculation is simplified to:

static final int spread(int h) {
    return (h ^ (h >>> 16)) & 0x7fffffff;
}

When a bucket’s list length reaches 8 and the table size is less than 64, the list is transformed into a red‑black tree; otherwise the table is resized.

04 Core Method Analysis – put()

JDK 8 put()

public V put(K key, V value) {
    return putVal(key, value, false);
}
final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
    int hash = spread(key.hashCode());
    int binCount = 0;
    // ... core insertion logic ...
}

The method first checks for nulls, computes the hash, then attempts a lock‑free CAS insertion. If the bucket is empty, it inserts directly; otherwise it synchronizes on the bucket head, handles collisions (list or tree), and may trigger resizing.

05 Resizing Mechanisms Comparison

JDK 7 – each Segment resizes independently when its element count exceeds capacity × loadFactor. The new array is twice the old size, and entries are rehashed within that segment.

void rehash() {
    HashEntry<K,V>[] oldTable = table;
    int oldCapacity = oldTable.length;
    if (oldCapacity >= MAXIMUM_CAPACITY) return;
    HashEntry<K,V>[] newTable = HashEntry.newArray(oldCapacity << 1);
    threshold = (int)(newTable.length * loadFactor);
    // migrate entries
    table = newTable;
}

JDK 8 – the whole table resizes together. Multiple threads can cooperate in the transfer; each thread locks only the bucket it is moving. A ForwardingNode marks migrated buckets, allowing reads to continue on the old table while writes assist the transfer.

06 Hash Calculation Deep Dive

JDK 7 hash() performs several bit‑shifts and XORs to disperse bits, but does not use the final “xor‑shift” perturbation found in HashMap.

private int hash(Object k) {
    int h = k.hashCode();
    h += (h << 15) ^ 0xffffcd7d;
    h ^= (h >>> 10);
    h += (h << 3);
    h ^= (h >>> 6);
    h += (h << 2) + (h << 14);
    return h ^ (h >>> 16);
}

JDK 8 spread() uses a single xor‑shift and masks the sign bit, making it faster and more suitable for CAS‑based bucket selection.

07 Usage Recommendations

For simple read‑only or low‑contention scenarios, HashMap is sufficient.

In high‑concurrency environments, prefer ConcurrentHashMap but still synchronize compound actions (e.g., check‑then‑act).

Iterators are weakly consistent; they reflect some, but not necessarily all, modifications.

Bulk operations like putAll are not atomic.

08 Summary

ConcurrentHashMap combines an array, linked list/red‑black tree, CAS, and fine‑grained synchronization to achieve near‑optimal performance in multithreaded Java applications. Understanding its macro evolution, microscopic implementation, hash computation, and resizing strategies enables developers to write more efficient and correct concurrent code.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Javaconcurrencythread safetyHashMapConcurrentHashMapJDK8JDK7
Programmer Null's Self-Cultivation
Written by

Programmer Null's Self-Cultivation

Focused on backend development technologies and sharing knowledge from programming project experiences.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.