Backend Development 10 min read

Why ConcurrentHashMap.get() in Java 8 Is Lock‑Free

The article explains how Java 8's ConcurrentHashMap implements a lock‑free get() operation by replacing the Segment design with Node objects, using volatile fields and CAS, and how the volatile‑marked table array ensures visibility during resizing, making reads both safe and efficient.

Top Architect
Top Architect
Top Architect
Why ConcurrentHashMap.get() in Java 8 Is Lock‑Free

In Java 8 the ConcurrentHashMap get() method is lock‑free, which raises the question: why does it not need any locking?

ConcurrentHashMap Overview

In JDK 1.7 the implementation relied on Segment + HashEntry + ReentrantLock . JDK 1.8 abandoned the bulky Segment design and switched to Node + CAS + synchronized to guarantee thread safety.

JDK 1.8 reduces lock granularity: JDK 1.7 locks at the Segment level (multiple HashEntry objects), while JDK 1.8 locks at the individual HashEntry (the first node).

The data structure becomes simpler, operations clearer, and because synchronized is used directly, the concept of segment locks disappears, increasing implementation complexity.

JDK 1.8 replaces long linked‑list buckets with red‑black trees when the list length exceeds a threshold, improving traversal performance.

get() Source Code (excerpt)

public V get(Object key) {
    Node
[] tab; Node
e, p; int n, eh; K ek;
    int h = spread(key.hashCode()); // compute hash
    if ((tab = table) != null && (n = tab.length) > 0 &&
        (e = tabAt(tab, (n - 1) & h)) != null) { // read first node
        if ((eh = e.hash) == h) { // first node matches
            if ((ek = e.key) == key || (ek != null && key.equals(ek)))
                return e.val;
        }
        // eh < 0 indicates special nodes during resize or tree bin
        else if (eh < 0)
            return (p = e.find(h, key)) != null ? p.val : null;
        while ((e = e.next) != null) { // traverse chain
            if (e.hash == h && ((ek = e.key) == key || (ek != null && key.equals(ek))))
                return e.val;
        }
    }
    return null;
}

The method never acquires a lock; visibility and ordering are guaranteed by the volatile modifiers on the relevant fields.

Role of volatile

Java's volatile keyword provides visibility and ordering guarantees but not atomicity. Ordinary shared variables may have their updates delayed in caches, causing other threads to read stale values. Declaring a variable volatile forces writes to be flushed to main memory and invalidates cached copies in other CPUs, ensuring that subsequent reads see the latest value.

For reference‑type fields such as arrays, volatile only makes the reference itself visible; the contents are not automatically volatile. The array field in ConcurrentHashMap is declared as:

transient volatile Node
[] table;

This volatile array ensures that when the table is resized, the new reference becomes visible to all threads.

Node Class with Volatile Members

static class Node
implements Map.Entry
{
    final int hash;
    final K key;
    volatile V val;               // visible to other threads
    volatile Node
next;       // visible to other threads
    // constructor and other methods omitted for brevity
    Node
find(int h, Object k) {
        Node
e = this;
        if (k != null) {
            do {
                K ek;
                if (e.hash == h && ((ek = e.key) == k || (ek != null && k.equals(ek))))
                    return e;
            } while ((e = e.next) != null);
        }
        return null;
    }
}

Because val and next are volatile, updates made by one thread are immediately visible to others, allowing the get() operation to read a consistent state without acquiring a lock.

Summary

In JDK 1.8 ConcurrentHashMap's get() is lock‑free, contributing to higher performance compared with Hashtable or Collections.synchronizedMap().

The lock‑free property stems from the volatile modifiers on Node fields, not from the volatile array itself.

The volatile array table primarily guarantees visibility of the new bucket array during resizing.

JavaBackend DevelopmentConcurrencyConcurrentHashMapvolatilelock-free
Top Architect
Written by

Top Architect

Top Architect focuses on sharing practical architecture knowledge, covering enterprise, system, website, large‑scale distributed, and high‑availability architectures, plus architecture adjustments using internet technologies. We welcome idea‑driven, sharing‑oriented architects to exchange and learn together.

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.