Java Segmented Lock
🧩 1. Problem Background: Why Do We Need a “Segmented Lock”?
In a multithreaded environment, if you want multiple threads to safely access a shared Map (e.g., HashMap), the simplest approach is:
Map<K, V> map = Collections.synchronizedMap(new HashMap<>());This locks the entire Map. → Result: any thread accessing the Map must wait for the lock, even if they operate on different keys.
Performance issue example:
- Thread A executes
put(key1, value1) - Thread B executes
get(key2)
Even though they access different keys, they block each other. 😩
The solution: segmented lock.
⚙️ 2. Core Idea of Segmented Lock
In one sentence:
Split a big lock into multiple smaller locks, each segment managing a portion of the data.
Visualization:
ConcurrentHashMap
├── Segment[0] — manages a portion of buckets
├── Segment[1] — manages a portion of buckets
├── Segment[2] — manages a portion of buckets
└── ...Each Segment has its own lock. When accessing a key:
- Hash the key to determine its segment
- Lock only that segment
- Other segments remain accessible
👉 Concurrency increases significantly.
🧠 3. Java Implementation (JDK 1.7 Example)
In JDK 1.7 ConcurrentHashMap:
- Internally:
Segment<K,V>[] segments - Each
SegmentextendsReentrantLock - Each
Segmentmaintains its own smallHashEntry[]
Diagram:
ConcurrentHashMap
├── Segment[0] → Lock A → HashEntry[] A
├── Segment[1] → Lock B → HashEntry[] B
├── Segment[2] → Lock C → HashEntry[] C
└── ...When executing:
map.put("key", value);Flow roughly:
- Compute the key’s hash
- Locate the corresponding Segment
- Acquire the segment’s lock
- Modify the internal bucket/chain
- Release the lock
⚡ Threads operating on different segments can run in parallel.
🚀 4. Changes in JDK 1.8+
In JDK 1.8+, ConcurrentHashMap removed the explicit Segment structure, adopting finer-grained Node + CAS + synchronized:
- No explicit segments
- Use
synchronizedon individual buckets or tree nodes - CAS reduces lock contention
Conceptually, it’s still the segmented lock idea:
Lock only the necessary portion, reducing contention.
📊 5. Comparison Table
| Approach | Lock Granularity | Feature | Analogy |
|---|---|---|---|
HashMap + synchronized | Whole Map | Simple but slow | Only one person at a time |
ConcurrentHashMap (JDK 1.7) | Segment-level | Parallel per segment | Multiple supermarket checkout counters |
ConcurrentHashMap (JDK 1.8+) | Node-level + CAS | Finer granularity | Lock each shelf individually |
🧩 6. Example Code (Conceptual)
public class SegmentLockDemo {
private final int segmentCount = 16;
private final Object[] locks = new Object[segmentCount];
private final Map<Integer, String>[] maps = new Map[segmentCount];
public SegmentLockDemo() {
for (int i = 0; i < segmentCount; i++) {
locks[i] = new Object();
maps[i] = new HashMap<>();
}
}
private int getSegmentIndex(Object key) {
return key.hashCode() & (segmentCount - 1);
}
public void put(Integer key, String value) {
int index = getSegmentIndex(key);
synchronized (locks[index]) {
maps[index].put(key, value);
}
}
public String get(Integer key) {
int index = getSegmentIndex(key);
synchronized (locks[index]) {
return maps[index].get(key);
}
}
}Each key maps to a specific lock/segment, enabling concurrent access for different keys.
✅ 7. Key Takeaway
Segmented lock is a concurrency strategy that trades space for time. By splitting a single global lock into multiple independent locks, it significantly improves concurrent performance.
- JDK 1.7: explicit
Segmentimplementation- JDK 1.8+: evolved into finer-grained Node-level locks + CAS.