Synchronized HashMap in Java
A Synchronized HashMap is simply a thread-safe version of HashMap, created using the Collections.synchronizedMap() wrapper method.
It ensures only one thread can access the map at a time, providing full synchronization (global lock).
What is a Synchronized HashMap?
A Synchronized HashMap is a thread-safe version of HashMap.
If multiple threads modify it simultaneously, it may cause:
- Data inconsistency
- Race conditions
ConcurrentModificationException- Even structure corruption (in older JVMs)
To make a HashMap thread-safe, Java provides:
Map<K, V> syncMap = Collections.synchronizedMap(new HashMap<>());
This wraps the HashMap inside a synchronized wrapper.
All operations (put(), get(), remove()) become synchronized internally.
Package
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
How Synchronized HashMap Works Internally
It uses a single lock for the entire map.
Simplified internal code:
public V put(K key, V value) {
synchronized (mutex) {
return m.put(key, value);
}
}
Effects:
- Thread-safe
- Slower when multiple threads operate
- Only one thread can access any map operation at a time
Creating a Synchronized HashMap
1. Using Collections.synchronizedMap()
Map<String, Integer> map =
Collections.synchronizedMap(new HashMap<>());
2. Simple Example
Map<String, Integer> map =
Collections.synchronizedMap(new HashMap<>());
map.put("A", 1);
map.put("B", 2);
System.out.println(map.get("A"));
Iterating a Synchronized HashMap (IMPORTANT)
Even though the map is synchronized, iteration IS NOT thread-safe.
You must use a synchronized block:
Map<String, Integer> map =
Collections.synchronizedMap(new HashMap<>());
synchronized (map) {
for (Map.Entry<String, Integer> entry : map.entrySet()) {
System.out.println(entry.getKey() + " = " + entry.getValue());
}
}
Skipping the synchronized block may cause ConcurrentModificationException.
Complete Example
import java.util.*;
public class Main {
public static void main(String[] args) {
Map<String, Integer> map =
Collections.synchronizedMap(new HashMap<>());
map.put("A", 1);
map.put("B", 2);
synchronized (map) {
for (String key : map.keySet()) {
System.out.println(key + " : " + map.get(key));
}
}
}
}
Drawbacks of SynchronizedHashMap
| Issue | Explanation |
|---|---|
| Slow | Entire map is locked for every operation |
| No scalability | Not good for high concurrency |
| Weak concurrency | Iteration needs manual synchronization |
Alternatives to Synchronized HashMap
| Option | Thread-safe | Performance | Notes |
|---|---|---|---|
| Collections.synchronizedMap | Yes | Slow | Uses single lock |
| Hashtable | Yes | Slow | Legacy, synchronized methods |
| ConcurrentHashMap | Yes | Fast | Fine-grained locking, best choice |
Difference: SynchronizedMap vs ConcurrentHashMap
| Feature | SynchronizedMap | ConcurrentHashMap |
|---|---|---|
| Thread Safety | Thread-safe using global lock | Thread-safe using fine-grained locking (Java 8+ uses CAS + bins) |
| Locking Mechanism | Locks the entire map for every operation | Locks only portions (buckets/segments), allowing concurrent reads/writes |
| Performance | Slow under heavy concurrency | High-performance, scalable under multiple threads |
| Null Keys / Values | Not allowed | Not allowed |
| Iteration | Fail-fast (throws ConcurrentModificationException) | Weakly consistent (does not throw exceptions, may reflect some updates) |
| Read Operations | Require lock → slower | Mostly lock-free → faster |
| Write Operations | Single thread at a time | Multiple threads can update concurrently |
| Use Case | Simple thread safety for small maps | High-performance concurrent applications |
Difference: SynchronizedMap vs Hashtable vs ConcurrentHashMap
| Feature | Hashtable | SynchronizedMap | ConcurrentHashMap |
|---|---|---|---|
| Thread Safety | Yes (fully synchronized) | Yes (wrapper makes it synchronized) | Yes (high-performance concurrency) |
| Synchronization Type | Method-level locking | Object-level locking (on entire map) | Fine-grained locking (bucket-level) |
| Performance | Slowest (full map lock) | Slow (full map lock) | Fastest (no global lock) |
| Allows Null Key/Value | No null key/value | No null key/value | No null key/value |
| Concurrency Level | Very low | Very low | Very high (multiple threads can update safely) |
| Iteration Behavior | Fail-Fast | Fail-Fast | Weakly Consistent (no exceptions) |
| Introduced In | Java 1.0 | Java 1.2 | Java 1.5 |
| Use Case | Legacy code | Wrap a normal map for basic thread safety | High-performance concurrent applications |
| Underlying Structure | HashTable | Any Map (usually HashMap) | Hash buckets (Java 8 uses CAS + tree bins) |
| Null Handling Reason | Checking null causes ambiguity in sync methods | Follows Hashtable rules | Avoid ambiguity in concurrent operations |
When to Use Synchronized HashMap?
Use it when:
- Few threads
- Small data volume
- Performance is not critical
- You need simple, full synchronization
Avoid it when:
- Many threads
- High read/write operations
- You need scalability
In such cases, always use ConcurrentHashMap.
Real-Life Use Cases
- Small shared configuration maps
- Simple utilities in multi-threaded environments
- Legacy code needing thread-safety
Points to Remember
- HashMap is not thread-safe
- SynchronizedMap adds global locking
- Must use manual synchronization during iteration
- Slower for multi-threaded applications
- ConcurrentHashMap is the recommended modern alternative
