Advanced Java October 06 ,2025

How ConcurrentHashMap Works in Java

Deep Dive into Thread-Safe Hashing

Introduction

In Java, a HashMap is not thread-safe, meaning it cannot be safely used by multiple threads without external synchronization.
To address this, Java provides the ConcurrentHashMap, a high-performance, thread-safe variant of HashMap that allows concurrent read and write operations without locking the entire map.

This blog will cover:

  • Why ConcurrentHashMap is needed.
  • Internal working and structure.
  • Key features and concurrency mechanisms.
  • How to use it effectively.
  • A custom simplified implementation concept.

1. Why Not Use HashMap in Multi-threading?

When multiple threads access and modify a HashMap concurrently:

  • Data inconsistency can occur.
  • Infinite loops can happen (due to structural modification during rehashing).
  • Race conditions and corruption of data.

Example:

Map map = new HashMap<>();
Runnable task = () -> map.put(1, "Java");
new Thread(task).start();
new Thread(task).start();

This may result in inconsistent results because HashMap is not synchronized.

2. Introduction to ConcurrentHashMap

ConcurrentHashMap solves this problem by:

  • Allowing multiple threads to read without locking.
  • Allowing a limited number of threads to write concurrently using fine-grained locking.

Key benefits:

  • High concurrency and performance.
  • No need for external synchronization.
  • Avoids ConcurrentModificationException in most cases.

3. Internal Working

Java 8 and Later

In Java 8+, ConcurrentHashMap uses a **combination of:

  • Hash table (array of bins).
  • Lock striping and CAS (Compare-And-Swap) for concurrency.
  • Tree bins (red-black trees) for handling high-collision scenarios.

Structure:

Table → Array of Node
Each Node contains:
  - hash
  - key
  - value
  - next (for collision handling)

Segmentation Removed

Earlier Java versions (before Java 8) used Segment locks.
Java 8 replaced segments with a synchronized block at the bin level to improve performance and reduce memory overhead.

4. Concurrency Mechanisms

4.1 Lock Striping

Instead of locking the entire table, only a portion of the table (a bin) is locked during updates.
This allows multiple threads to operate on different bins without interference.

4.2 CAS (Compare-And-Swap)

A lock-free mechanism for reads and updates when possible.
It minimizes locking and improves performance for read-heavy workloads.

4.3 Tree Bins

When collisions increase in a single bin, the linked list of entries converts into a balanced tree for faster lookup (O(log n) instead of O(n)).

5. Key Methods and Their Behavior

MethodThread-SafetyNotes
put()Thread-safeUses bin-level locking
get()Lock-free readUses volatile reads and CAS
remove()Thread-safeBin-level locking
size()Approximate in concurrent contextExpensive due to locking
computeIfAbsent()Thread-safeComputes value atomically if absent

Example:

import java.util.concurrent.*;

public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentHashMap map = new ConcurrentHashMap<>();

        map.put(1, "Java");
        map.put(2, "Python");
        map.put(3, "C++");

        map.forEach((k, v) -> System.out.println(k + " → " + v));

        map.computeIfAbsent(4, key -> "Go");
        System.out.println("After computeIfAbsent: " + map);
    }
}

6. Iteration in ConcurrentHashMap

ConcurrentHashMap supports weakly consistent iterators, meaning:

  • They do not throw ConcurrentModificationException.
  • They may or may not reflect updates after the iterator was created.
  • They guarantee no element is returned twice.

Example:

ConcurrentHashMap map = new ConcurrentHashMap<>();
map.put(1, "Java");
map.put(2, "Python");

for (Map.Entry entry : map.entrySet()) {
    System.out.println(entry);
}

7. Performance Characteristics

  • High performance in read-heavy workloads due to lock-free reads.
  • Moderate contention in write-heavy workloads depending on bin locking.
  • Better scalability than synchronized HashMap or Hashtable.

8. Custom Implementation Concept 

A full custom ConcurrentHashMap is complex, but here’s a conceptual design:

Step 1 — Define the Bucket Structure

We need buckets to store entries and locks for thread safety.

import java.util.concurrent.locks.ReentrantLock;

static class Bucket {
    private Node head;
    private final ReentrantLock lock = new ReentrantLock();

    void put(K key, V value) {
        lock.lock();
        try {
            if (head == null) {
                head = new Node<>(key, value);
            } else {
                Node current = head;
                while (current != null) {
                    if (current.key.equals(key)) {
                        current.value = value; // update value
                        return;
                    }
                    if (current.next == null) {
                        current.next = new Node<>(key, value);
                        return;
                    }
                    current = current.next;
                }
            }
        } finally {
            lock.unlock();
        }
    }

    V get(K key) {
        lock.lock();
        try {
            Node current = head;
            while (current != null) {
                if (current.key.equals(key)) {
                    return current.value;
                }
                current = current.next;
            }
            return null;
        } finally {
            lock.unlock();
        }
    }
}

Step 2 — Define the Node Structure

Each bucket will store its entries as linked nodes.

static class Node {
    K key;
    V value;
    Node next;

    Node(K key, V value) {
        this.key = key;
        this.value = value;
    }
}

Step 3 — Create the Main ConcurrentHashMap Class

This class will store an array of buckets and manage hashing.

public class CustomConcurrentHashMap {
    private final int capacity = 16;
    private final Bucket[] table;

    public CustomConcurrentHashMap() {
        table = new Bucket[capacity];
        for (int i = 0; i < capacity; i++) {
            table[i] = new Bucket<>();
        }
    }

    private int getBucketIndex(K key) {
        return Math.abs(key.hashCode() % capacity);
    }
}

Step 4 — Implement put() Method

This method hashes the key and inserts it into the correct bucket.

public void put(K key, V value) {
    int index = getBucketIndex(key);
    table[index].put(key, value);
}

Step 5 — Implement get() Method

This method retrieves the value for a given key safely.

public V get(K key) {
    int index = getBucketIndex(key);
    return table[index].get(key);
}

Step 6 — Full CustomConcurrentHashMap Code

Here’s the complete working code combining all the steps.

import java.util.concurrent.locks.ReentrantLock;

public class CustomConcurrentHashMap {
    private final int capacity = 16;
    private final Bucket[] table;

    public CustomConcurrentHashMap() {
        table = new Bucket[capacity];
        for (int i = 0; i < capacity; i++) {
            table[i] = new Bucket<>();
        }
    }

    private int getBucketIndex(K key) {
        return Math.abs(key.hashCode() % capacity);
    }

    public void put(K key, V value) {
        int index = getBucketIndex(key);
        table[index].put(key, value);
    }

    public V get(K key) {
        int index = getBucketIndex(key);
        return table[index].get(key);
    }

    static class Bucket {
        private Node head;
        private final ReentrantLock lock = new ReentrantLock();

        void put(K key, V value) {
            lock.lock();
            try {
                if (head == null) {
                    head = new Node<>(key, value);
                } else {
                    Node current = head;
                    while (current != null) {
                        if (current.key.equals(key)) {
                            current.value = value;
                            return;
                        }
                        if (current.next == null) {
                            current.next = new Node<>(key, value);
                            return;
                        }
                        current = current.next;
                    }
                }
            } finally {
                lock.unlock();
            }
        }

        V get(K key) {
            lock.lock();
            try {
                Node current = head;
                while (current != null) {
                    if (current.key.equals(key)) {
                        return current.value;
                    }
                    current = current.next;
                }
                return null;
            } finally {
                lock.unlock();
            }
        }
    }

    static class Node {
        K key;
        V value;
        Node next;

        Node(K key, V value) {
            this.key = key;
            this.value = value;
        }
    }
}

Step 7 — Testing the Custom ConcurrentHashMap

public class TestCustomConcurrentHashMap {
    public static void main(String[] args) {
        CustomConcurrentHashMap map = new CustomConcurrentHashMap<>();

        map.put("Java", "Platform");
        map.put("Python", "Language");
        map.put("C++", "Programming");

        System.out.println("Java: " + map.get("Java"));
        System.out.println("Python: " + map.get("Python"));
        System.out.println("C++: " + map.get("C++"));
    }
}

Expected Output:

Java: Platform
Python: Language
C++: Programming

 

9. Advantages of ConcurrentHashMap

  • High throughput in multi-threaded environments.
  • Lock-free reads improve performance.
  • Safe concurrent modification.
  • Weakly consistent iterators avoid exceptions.

10. Disadvantages of ConcurrentHashMap

  • Slightly higher memory consumption due to locks and internal structure.
  • Slightly more complex iteration behavior.
  • Writes are slower compared to HashMap because of locking.

11. Real-World Applications

  • Caching systems (where high concurrency is needed).
  • Shared state in multi-threaded applications.
  • Real-time analytics processing.
  • Thread-safe configuration maps.

Conclusion

In this blog, we have explored:

  • Why ConcurrentHashMap is necessary for thread safety.
  • How it works internally.
  • Its concurrency mechanisms.
  • Key advantages and disadvantages.
  • A conceptual design of a custom concurrent hash map.

Understanding ConcurrentHashMap is crucial for designing highly concurrent applications in Java that require thread-safe access to shared resources.

 

Next Blog- Comparable vs Comparator in Java

 

 

 

Sanjiv
0

You must logged in to post comments.

Related Blogs

Generics P...
Advanced Java August 08 ,2025

Generics Part- 2

Collection...
Advanced Java July 07 ,2025

Collections Framewor...

Mastering...
Advanced Java August 08 ,2025

Mastering Java Multi...

Annotation...
Advanced Java August 08 ,2025

Annotations

Java Memor...
Advanced Java August 08 ,2025

Java Memory Manageme...

Java Lambd...
Advanced Java August 08 ,2025

Java Lambda Expressi...

Java Funct...
Advanced Java August 08 ,2025

Java Functional Inte...

Java Strea...
Advanced Java August 08 ,2025

Java Stream API

JDBC (Java...
Advanced Java August 08 ,2025

JDBC (Java Database...

JDBC (Java...
Advanced Java September 09 ,2025

JDBC (Java Database...

Annotation...
Advanced Java August 08 ,2025

Annotations

Generics
Advanced Java August 08 ,2025

Generics

Java I/O (...
Advanced Java August 08 ,2025

Java I/O (NIO)

Introducti...
Advanced Java September 09 ,2025

Introduction to Desi...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Other Prin...
Advanced Java September 09 ,2025

Other Principles Beh...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Creational...
Advanced Java September 09 ,2025

Creational Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

In Creatio...
Advanced Java September 09 ,2025

In Creational Design...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Builder De...
Advanced Java September 09 ,2025

Builder Design Patte...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Structural...
Advanced Java September 09 ,2025

Structural Design Pa...

Design Pat...
Advanced Java September 09 ,2025

Design Patterns in J...

Chain of R...
Advanced Java September 09 ,2025

Chain of Responsibil...

Command De...
Advanced Java September 09 ,2025

Command Design Patte...

Interprete...
Advanced Java September 09 ,2025

Interpreter Design P...

Iterator D...
Advanced Java September 09 ,2025

Iterator Design Patt...

Mediator D...
Advanced Java September 09 ,2025

Mediator Design Patt...

Memento De...
Advanced Java September 09 ,2025

Memento Design Patte...

Observer D...
Advanced Java September 09 ,2025

Observer Design Patt...

State Desi...
Advanced Java September 09 ,2025

State Design Pattern...

Strategy D...
Advanced Java September 09 ,2025

Strategy Design Patt...

Template M...
Advanced Java September 09 ,2025

Template Method Desi...

Visitor De...
Advanced Java September 09 ,2025

Visitor Design Patte...

Prototype...
Advanced Java September 09 ,2025

Prototype Design Pat...

Java 8+ Fe...
Advanced Java October 10 ,2025

Java 8+ Features

SOLID Prin...
Advanced Java October 10 ,2025

SOLID Principles in...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

Custom Imp...
Advanced Java October 10 ,2025

Custom Implementatio...

How Iterat...
Advanced Java October 10 ,2025

How Iterators Work i...

Comparable...
Advanced Java October 10 ,2025

Comparable vs Compar...

Get In Touch

G06, Kristal Olivine Bellandur near Bangalore Central Mall, Bangalore Karnataka, 560103

+91-8076082435

techiefreak87@gmail.com