← Back to list

Understanding ConcurrentHashMap Internal Working in Java

Introduction

Govinda Ekabote · 2026-06-24 21:58 · 20 claps · 4.4 min read
#java #collections-framework #concurrenthashmap #core-java #java-interview-questions
Open on Medium ↗

Understanding ConcurrentHashMap Internal Working in Java

Introduction

If you’re a Java developer, you’ve probably used HashMap for storing key-value pairs. But when multiple threads access it simultaneously, HashMap can break. That’s where ConcurrentHashMap comes to the rescue!

In this article, we’ll dive deep into how ConcurrentHashMap works internally, making it thread-safe without sacrificing performance.

Why Not Synchronized HashMap?

Before we explore ConcurrentHashMap, let’s understand the problem:

// ❌ BAD: HashMap in multi-threaded environment
Map<String, Integer> map = new HashMap<>();
// Can cause infinite loops, data corruption, or ConcurrentModificationException
// ✅ GOOD: ConcurrentHashMap handles concurrency
Map<String, Integer> map = new ConcurrentHashMap<>();
// Works perfectly in multi-threaded environment

Internal Architecture (Java 8+)

  1. The Segment-Based Approach (Java 7) Before Java 8, ConcurrentHashMap used Segments — multiple locks for different parts of the map.

2. CAS + Synchronized (Java 8+) — The Modern Way In Java 8+, ConcurrentHashMap uses

  • CAS (Compare-And-Swap) for node updates
  • Synchronized blocks only on specific nodes
  • Tree bins for collision handling

Key Components

1. Table (Node Array)

transient volatile Node<K,V>[] table;

The main array containing buckets (bins). Each bucket can contain:

  • Single Node (if no collision)
  • Linked List (if few collisions)
  • Red-Black Tree (if many collisions — threshold = 8)

2. Node Class

static class Node<K,V> implements Map.Entry<K,V> {
    final int hash;
    final K key;
    volatile V val;
    volatile Node<K,V> next;
}

3. TreeNode (For Tree Bins)

When a bin has > 8 nodes, it converts to a TreeBin for O(log n) lookup instead of O(n).

Core Operations Explained

  1. put() Operation
public V put(K key, V value) {
    return putVal(key, value, false);
}

Steps:

  1. Calculate hash
  2. If table empty, initialize using CAS
  3. Find bin index: (n - 1) & hash
  4. If bin is empty, create Node via CAS
  5. If bin exists, lock using synchronized on that bin
  6. Traverse list/tree and update or add node

2. get() Operation

public V get(Object key) {
    Node<K,V>[] tab; Node<K,V> e, p; int n, eh; K ek;
    int h = spread(key.hashCode());
    // ... find and return value
}

Key Points:

  • No locking! (Reads are lock-free)
  • Uses volatile to ensure visibility
  • If in tree, search tree; else traverse list

3. size() Operation

public int size() {
    long n = sumCount();
    return ((n < 0L) ? 0 : (n > (long)Integer.MAX_VALUE) ? 
            Integer.MAX_VALUE : (int)n);
}
  • Maintains a baseCount + CounterCell[] for counting
  • Updates use CAS to avoid blocking

Concurrency Control Mechanisms

1. CAS (Compare-And-Swap)

Used for lock-free operations:

  • Initializing table
  • Adding first node to empty bin
  • Updating counters
// Example of CAS usage
if (U.compareAndSwapInt(this, SIZECTL, sc, sc - 1)) {
    // Success
}

2. Synchronized (Fine-Grained)

  • Used only when updating existing bins
  • Lock is on the bin node, not the entire table
  • Allows multiple threads to update different bins simultaneously

3. volatile Keyword

  • Ensures visibility across threads
  • Used for table, next, val fields
  • Changes are immediately visible to other threads

4. Resizing Mechanism

When the map needs to resize:

  1. Multi-threaded resizing: Each thread helps resize
  2. Transfer: Old table → New table (double size)
  3. ForwardingNode: Pointers to new table during resize
// When resizing, threads can help transfer nodes
else if ((fh = f.hash) == MOVED)
    tab = helpTransfer(tab, f);

Best Practices

✅ DO:

// Use for concurrent access
ConcurrentHashMap<String, Integer> map = new ConcurrentHashMap<>();

// Use compute methods for atomic updates
map.compute(key, (k, v) -> v == null ? 1 : v + 1);

❌ DON’T:

// Don't use external synchronization
synchronized(map) { /* defeats the purpose! */ }

// Don't use null keys or values (HashMap allows null)
map.put(null, "value"); // ❌ NullPointerException

Key Takeaways

  1. Thread-safe by default — No external synchronization needed
  2. High performance — Better than synchronized maps under concurrency
  3. Lock-free reads — get() operations never block
  4. Fine-grained locking — Only specific bins are locked during writes
  5. CAS operations — For lock-free updates
  6. Tree bins — For handling hash collisions efficiently

Conclusion

ConcurrentHashMap represents the gold standard for concurrent collections in Java. By combining:

  • Lock-free techniques (CAS)
  • Fine-grained locking (synchronized on bins)
  • Smart data structures (tree bins)
  • Multi-threaded resizing

…it provides excellent performance while maintaining thread safety. Understanding its internals helps you use it effectively and appreciate the engineering behind it.

Remember: Use ConcurrentHashMap when you need a thread-safe map with multiple readers and writers. For single-threaded scenarios, stick with HashMap for better performance.

Found this useful? Drop a clap 👏 — it helps other developers find it. Questions? Leave a comment below.

👋 Let’s Connect! If you found this article helpful or want to chat more about JavaScript, Node.js, or web development in general, feel free to connect with me. I love learning from the community and sharing knowledge. 🔗 Connect with me on LinkedIn: 👉 Govinda Ekbote — LinkedIn Profile

Let’s learn and grow together in the dev community! 🚀


메타데이터
post_id
c715f9adddd0
slug
understanding-concurrenthashmap-internal-working-in-java-c715f9adddd0
url
https://medium.com/@govindaekbote7/understanding-concurrenthashmap-internal-working-in-java-c715f9adddd0
canonical_url
https://medium.com/@govindaekbote7/understanding-concurrenthashmap-internal-working-in-java-c715f9adddd0
author_url
https://medium.com/@govindaekbote7
status
ok
fetched_at
2026-08-10 06:01:41