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 ConcurrentModificationException if 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(), and compute() 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

Popular posts from this blog

Spring Boot on AWS EC2: Upload to S3 Securely Using IAM Role

Java Streams Intermediate Operations Explained with Examples