Fundamentals 11 min read

Evolution of Java ConcurrentHashMap: From Segment Locks to CAS + synchronized (Java 7 vs Java 8)

This article examines the evolution of Java's ConcurrentHashMap, comparing the segment‑lock implementation in Java 7 with the CAS‑plus‑synchronized, bucket‑level locking and red‑black tree enhancements introduced in Java 8, covering lock mechanisms, data structures, resizing strategies, core operations, performance and suitable use cases.

Cognitive Technology Team
Cognitive Technology Team
Cognitive Technology Team
Evolution of Java ConcurrentHashMap: From Segment Locks to CAS + synchronized (Java 7 vs Java 8)

ConcurrentHashMap is a thread‑safe hash table implementation in Java's concurrency package, designed to address performance and thread‑safety challenges in high‑concurrency scenarios. Its implementation has evolved from segment locks in Java 7 to a combination of CAS, synchronized and red‑black trees in Java 8.

1. Evolution of Lock Mechanism

Java 7: Segment Locks

Implementation principle : The map is divided into a fixed number of segments (default 16). Each Segment extends ReentrantLock and manages an independent hash table ( HashEntry array).

Lock granularity : Segment‑level (coarse).

Concurrency : Up to 16 threads (limited by segment count).

Drawbacks : Fixed segment count, whole‑segment lock during writes leads to contention.

Code example :

static final class Segment<K,V> extends ReentrantLock {
    transient volatile HashEntry<K,V>[] table;
    transient int count;
}

Mermaid diagram (image omitted).

Java 8: CAS + synchronized (bucket‑level lock)

Implementation principle : Removes segment locks; uses a Node array (buckets) to store entries.

Lock object : Only the head of a conflicting bucket or the root of a red‑black tree is locked.

Lock type : Combination of CAS (lock‑free) and synchronized (lightweight).

Concurrency : Theoretically unlimited, bounded only by CPU cores.

Core optimizations :

Finer lock granularity (bucket‑level) reduces contention.

Lock‑free reads using volatile for visibility.

Data structure: array + linked list + red‑black tree (treeified when list length ≥ 8 and table size ≥ 64).

Code example :

final V putVal(K key, V value, boolean onlyIfAbsent) {
    int hash = spread(key.hashCode());
    Node<K,V>[] tab; Node<K,V> p; int n, i;
    if ((tab = table) == null || (n = tab.length) == 0)
        n = (tab = initTable()).length;
    if ((p = tabAt(tab, i = (n - 1) & hash)) == null)
        tab[i] = new Node<>(hash, key, value, null);
    else {
        Node<K,V> e; K k;
        if (p.hash == hash && ((k = p.key) == key || (key != null && key.equals(k))))
            e = p;
        else if (p instanceof TreeNode)
            e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
        else {
            for (int binCount = 0; ; ++binCount) {
                if ((e = p.next) == null) {
                    p.next = new Node<>(hash, key, value, null);
                    if (binCount >= TREEIFY_THRESHOLD - 1)
                        treeifyBin(tab, i);
                    break;
                }
                if (e.hash == hash && ((k = e.key) == key || (key != null && key.equals(k))))
                    break;
                p = e;
            }
        }
        if (e != null)
            return e.value;
    }
    addCount(1L, binCount);
    return null;
}

Mermaid diagram (image omitted).

2. Data Structure Upgrade

Java 7: Array + Linked List

Linked list stores colliding entries; performance degrades to O(n) for long chains.

Java 8: Array + Linked List + Red‑Black Tree

When a bucket’s list length reaches 8 and the table size is at least 64, the list is transformed into a red‑black tree, reducing lookup complexity to O(log n).

If the tree size falls to ≤ 6, it collapses back to a list.

Advantages: Faster queries and thread‑safe tree operations via synchronized and CAS.

Code example :

static final class TreeBin<K,V> extends Node<K,V> {
    TreeNode<K,V> root; // red‑black tree root
    volatile TreeNode<K,V> first; // list head
    volatile Thread waiter; // waiting thread
    volatile int lockState; // lock state
}

3. Resizing Optimization

Java 7: Segment‑wise resizing

Each segment resizes independently, leading to high memory overhead and limited parallelism.

Java 8: Global resizing with multi‑thread cooperation

Resize is triggered when size exceeds capacity × loadFactor (default 0.75).

Progressive migration uses ForwardingNode to allow multiple threads to move entries concurrently.

Code example :

// Java 8 sizeCtl field controls resizing
private transient volatile int sizeCtl;
// -1: table is initializing
// -N: N‑1 threads are resizing
// positive: initial capacity or resize threshold after initialization

4. Core Operation Comparison

Operation

Java 7

Java 8

Put

Locate segment → lock → insert/update → unlock

Locate bucket → CAS insert empty bucket →

synchronized

lock head → insert/update

Get

No lock, read

HashEntry

directly

No lock, traverse list or red‑black tree

Remove

Locate segment → lock → delete → unlock

Locate bucket →

synchronized

lock head → delete

Resize

Segment‑wise resizing

Global resizing with multi‑thread migration

5. Performance and Use Cases

Java 7

Advantages: Simple implementation, suitable for moderate concurrency.

Drawbacks: Fixed segment count, lock contention.

Typical scenarios: Small‑to‑medium systems with modest concurrency requirements.

Java 8

Advantages: Higher concurrency due to finer lock granularity, efficient queries via red‑black trees, dynamic resizing.

Drawbacks: Higher implementation complexity.

Typical scenarios: High‑concurrency systems such as e‑commerce flash sales or distributed caches.

6. Summary Comparison Table

Feature

Java 7

Java 8

Lock mechanism

Segment lock

CAS +

synchronized

(bucket‑level)

Data structure

Segment + HashEntry array + list

Node array + list + red‑black tree

Lock granularity

Segment level

Bucket level

Concurrency performance

Medium (limited by segment count)

High (multi‑thread cooperation)

Resizing method

Segment‑wise

Global with progressive migration

Query complexity

O(n) (list)

O(log n) (tree)

Implementation complexity

Higher (segment logic)

Higher (tree operations)

Applicable scenario

Medium concurrency

High concurrency

7. One‑sentence Summary

Java 7: Segment‑lock mechanism, suitable for moderate concurrency.

Java 8: CAS + synchronized fine‑grained locking, ideal for high concurrency.

Understanding the differences between Java 7 and Java 8 implementations of ConcurrentHashMap helps developers choose the appropriate version for efficient concurrent control in multithreaded environments.

JavaperformanceconcurrencyDataStructurelockingConcurrentHashMap
Cognitive Technology Team
Written by

Cognitive Technology Team

Cognitive Technology Team regularly delivers the latest IT news, original content, programming tutorials and experience sharing, with daily perks awaiting you.

0 followers
Reader feedback

How this landed with the community

login 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.