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.
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.
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.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.