ConcurrentHashMap vs Synchronized HashMap in Java
Introduction
In multi-threaded Java applications, managing shared data safely and efficiently is crucial.
Two common approaches are using Synchronized HashMap (via
Collections.synchronizedMap(...)) and ConcurrentHashMap.
While both aim to provide thread-safety, their implementations and performance
characteristics differ significantly. This post explores these differences in detail.
What is a Synchronized HashMap?
- Created by wrapping a regular HashMap using:
Map<K, V> syncMap = Collections.synchronizedMap(new HashMap<>());
- Enforces synchronization at the object level, meaning only one thread can access the map at any time (read or write).
- Supports null keys and values since it relies on HashMap behavior.
- Iterators are fail-fast, throwing
ConcurrentModificationExceptionif the map is modified while iterating. - Simpler implementation, suitable when concurrency is low or performance is not critical.
What is ConcurrentHashMap?
- Introduced in Java 1.5 to provide a scalable thread-safe
Map. - Uses bucket-level locking (lock striping) instead of locking the entire map.
- Read operations are non-blocking, and write operations only lock specific buckets, allowing multiple threads to work concurrently.
- Does not allow null keys or values (insertion of null throws
NullPointerException). - Iterators are fail-safe (weakly consistent). They do not throw exceptions and can tolerate concurrent modifications.
- From Java 8 onward:
- Uses CAS (Compare-And-Swap) for certain operations, making it even more efficient.
- Introduced tree bins instead of linked lists for buckets with many collisions, improving performance from O(n) to O(log n).
- Provides atomic methods like
putIfAbsent(),remove(), andcompute()for safe concurrent updates.
Feature Comparison
| Feature | Synchronized HashMap | ConcurrentHashMap |
|---|---|---|
| Synchronization Strategy | Whole map (object-level) | Bucket/segment level (fine-grained locking) |
| Read Performance | Poor under high contention | Excellent (non-blocking) |
| Write Performance | Locks entire map | Locks only a bucket |
| Null Support | Allows null keys & values | No null keys/values allowed |
| Iterator Behavior | Fail-fast (throws exception) | Fail-safe (weakly consistent) |
| Atomic Operations | Not supported | Supported (putIfAbsent, compute, etc.) |
| Best Use Case | Low concurrency, simple apps | High concurrency, scalable apps |
When to Use What?
- Synchronized HashMap:
- Best for simple applications with minimal concurrency.
- Easy to use but can become a bottleneck in multi-threaded systems.
- ConcurrentHashMap:
- Ideal for high-performance, concurrent systems.
- Recommended when frequent read/write operations occur across multiple threads.
Real-World Use Cases
- Caching in multi-threaded applications.
- Storing session data in concurrent web applications.
- Counting word frequency or events in real-time streaming systems.
- Thread-safe registries like service locators or configuration maps.
Conclusion
Both Synchronized HashMap and ConcurrentHashMap provide thread-safety, but they serve different purposes. If performance and scalability are important in your multi-threaded application, ConcurrentHashMap is the better choice. For simple use cases with limited concurrency, a synchronized wrapper around HashMap may be sufficient.
Comments
Post a Comment