In‑Depth Explanation of Java ConcurrentHashMap Core Principles and Source Code
This article provides a comprehensive analysis of Java's ConcurrentHashMap, covering its underlying data structures, key attributes, core components such as Node, ForwardingNode, TreeBin, and TreeNode, and detailed explanations of the put, get, hash, and resizing algorithms with annotated source code examples.
ConcurrentHashMap is a thread‑safe container for key/value pairs that appears frequently in technical interviews, so a deep understanding of its implementation is essential.
The article first compares ConcurrentHashMap with HashMap, noting that although they share similar data structures, they are unrelated in the class hierarchy because ConcurrentHashMap inserts locking logic directly into its methods.
Key similarities include the use of array‑based storage and linked‑list structures, as both implement the Map interface and extend AbstractMap . Key differences involve the red‑black tree implementation (TreeNode vs. TreeBin) and the introduction of ForwardingNode for safe resizing.
Important Attributes
transient volatile Node[] table
private static final int DEFAULT_CAPACITY = 16;
static final int TREEIFY_THRESHOLD = 8
static final int MOVED = -1
static final int HASH_BITS = 0x7fffffff
private transient volatile Node[] nextTable;Core Components
Node : stores key, value, and a reference to the next node in a bucket.
ForwardingNode : used during resizing to point to the new table without holding key/value data.
TreeBin : holds a list of TreeNode objects and the root of the red‑black tree, managing tree‑level locking.
TreeNode : represents a node in the red‑black tree.
put Method
public V put(K key, V value) {
return putVal(key, value, false);
}The insertion process follows five steps: (1) initialize the table if null, (2) compute the bucket index, (3) handle forwarding nodes during resizing, (4) lock the bucket and insert into a linked list or tree, and (5) check whether resizing is required.
Thread‑Safety Mechanisms
Array initialization uses a combination of spin‑wait, CAS, and double‑checked locking to ensure only one thread creates the table.
When adding a new entry, the algorithm employs a spin loop with CAS for empty buckets and synchronized blocks for buckets that already contain nodes, guaranteeing exclusive access during modifications.
V oldVal = null;
// lock the bucket
synchronized (f) {
// update logic
}Tree operations lock the tree root to prevent concurrent rotations.
Hash Algorithm
static final int spread(int h) {
return (h ^ (h >>> 16)) & HASH_BITS;
}The spread method mixes high and low bits of the original hashCode and masks the sign bit, reducing collisions when the table size is a power of two.
Resizing (Transfer) Process
Resizing copies entries from the old table to a new, larger table while locking each bucket and inserting a ForwardingNode to indicate that the bucket is being moved. New puts encountering a forwarding node wait until the transfer completes, ensuring thread safety throughout the operation.
get Method
Lookup retrieves the bucket index, then either returns the value directly if the key matches, or traverses a linked list or red‑black tree using the same principles as HashMap .
Constructor
public ConcurrentHashMap(int initialCapacity) {
if (initialCapacity < 0)
throw new IllegalArgumentException();
int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
MAXIMUM_CAPACITY :
tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
this.sizeCtl = cap;
}The constructor does not allocate the table; it only sets sizeCtl based on a calculated capacity that is the smallest power‑of‑two greater than initialCapacity * 1.5 + 1 .
Utility Method tableSizeFor
private static final int tableSizeFor(int c) {
int n = c - 1;
n |= n >>> 1;
n |= n >>> 2;
n |= n >>> 4;
n |= n >>> 8;
n |= n >>> 16;
return (n < 0) ? 1 : (n >= MAXIMUM_CAPACITY) ? MAXIMUM_CAPACITY : n + 1;
}This method rounds up to the next power of two using bitwise operations.
Overall, the article offers a detailed walkthrough of ConcurrentHashMap’s internal design, emphasizing how locking, CAS, and bit‑level tricks combine to provide high‑performance, thread‑safe map operations.
Rare Earth Juejin Tech Community
Juejin, a tech community that helps developers grow.
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.