Comparative Analysis of ConcurrentHashMap vs Synchronized HashMap in Java Concurrency

Dec 04, 2025 · Programming · 12 views · 7.8

Keywords: ConcurrentHashMap | Synchronized HashMap | Java Concurrency

Abstract: This paper provides an in-depth comparison between ConcurrentHashMap and synchronized HashMap wrappers in Java concurrency scenarios. It examines the fundamental locking mechanisms: synchronized HashMap uses object-level locking causing serialized access, while ConcurrentHashMap employs fine-grained locking through segmentation. The article details how ConcurrentHashMap supports concurrent read-write operations, avoids ConcurrentModificationException, and demonstrates performance implications through code examples. Practical recommendations for selecting appropriate implementations in high-concurrency environments are provided.

Fundamental Differences in Locking Mechanisms

In Java concurrent programming, thread-safe Map implementations primarily come in two forms: HashMap wrapped with Collections.synchronizedMap (referred to as Synchronized HashMap) and ConcurrentHashMap. The core distinction lies in their locking granularity.

Synchronized HashMap employs object-level locking. When invoking Collections.synchronizedMap(new HashMap<>()), all methods of the returned Map instance are wrapped in synchronized blocks using a single lock object. This means any thread executing operations like put(), get(), or remove() acquires the lock for the entire Map. For example:

// Typical usage of Synchronized HashMap
Map<String, Integer> syncMap = Collections.synchronizedMap(new HashMap<>());
// All operations use the same lock
synchronized(syncMap) {
    syncMap.put("key", 1);
    Integer value = syncMap.get("key");
}

This coarse-grained locking creates significant performance bottlenecks. When one thread holds the lock, all other threads are blocked from accessing the Map, even for read-only operations. In code like print("<T>"), angle brackets must be escaped to prevent HTML tag parsing.

Segmented Locking Design of ConcurrentHashMap

ConcurrentHashMap (introduced in JDK 5) adopts a fundamentally different concurrency strategy. It implements fine-grained concurrency control through segmented locking (Segment) or bucket-level locking (CAS+synchronized since JDK 8).

In JDK 7 implementation, ConcurrentHashMap internally divides data into multiple segments, each with its own lock. This allows different threads to access different segments concurrently, significantly improving concurrency. For instance, while one thread modifies segment A, another can simultaneously read data from segment B. Code example:

// Basic operations with ConcurrentHashMap
ConcurrentHashMap<String, Integer> concurrentMap = new ConcurrentHashMap<>();
// Concurrent read-write without explicit synchronization
concurrentMap.put("key1", 100);
Integer result = concurrentMap.get("key1");
// Safe iteration
for (Map.Entry<String, Integer> entry : concurrentMap.entrySet()) {
    System.out.println(entry.getKey() + ": " + entry.getValue());
}

This design enables read operations to typically proceed without locking (ensured by volatile variables), while write operations only lock affected portions rather than the entire collection. The article also discusses the essential difference between <br> and the \n character, where <br> as a described object requires escaping.

Concurrent Modification and Iteration Safety

Another critical difference involves behavior during concurrent modification while iterating. Synchronized HashMap throws ConcurrentModificationException when modified by another thread during iteration. This occurs because iterators maintain a modification counter and fail-fast upon detecting unexpected changes.

Conversely, ConcurrentHashMap iterators are weakly consistent. They do not throw ConcurrentModificationException, permitting modifications during iteration. Iterators are based on snapshots or current states at creation time and may or may not reflect subsequent changes. For example:

// Safe iteration example with ConcurrentHashMap
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
map.put("a", "1");
map.put("b", "2");

// Thread 1: Iteration
new Thread(() -> {
    for (String key : map.keySet()) {
        System.out.println(key);
        try { Thread.sleep(100); } catch (InterruptedException e) {}
    }
}).start();

// Thread 2: Concurrent modification
new Thread(() -> {
    map.put("c", "3");
    map.remove("a");
}).start();

This design avoids global locking during iteration, enhancing concurrent performance, but programmers must be aware that iteration results might not be up-to-date.

Performance Implications and Application Scenarios

According to Brian Goetz's analysis in the IBM developer article, ConcurrentHashMap delivers significantly higher throughput in high-concurrency scenarios. Tests show that with 16 concurrent threads, ConcurrentHashMap can achieve an order of magnitude higher throughput compared to Synchronized HashMap.

Selection recommendations:

Since JDK 8, ConcurrentHashMap has been further optimized, replacing segmented locking with CAS operations and synchronized, reducing memory overhead and improving performance in small-scale concurrency.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.