# Part 8 — Concurrent Collections Deep Dive (Senior Java)
This is one of the highest-frequency topics in senior Java interviews.
Typical questions:
- Why is
HashMapnot thread-safe? - Why not simply use
Collections.synchronizedMap()? - How does
ConcurrentHashMapwork internally? - What changed from Java 7 to Java 8?
- What is CAS?
- When should you use
CopyOnWriteArrayList?
1. Why Normal Collections Fail in Multithreading¶
Consider:
Map<Integer, String> map = new HashMap<>();
Thread 1:
map.put(1, "A");
Thread 2:
map.put(2, "B");
Both threads modify the same internal structure simultaneously.
Possible consequences:
- Lost updates
- Corrupted buckets
- Inconsistent reads
- Resize corruption (especially problematic in older JDKs)
HashMap provides no synchronization.
2. Race Condition¶
Example:
Initial value:
count = 0
Thread 1:
Read 0
Thread 2:
Read 0
Thread 1:
Write 1
Thread 2:
Write 1
Expected:
2
Actual:
1
This is a race condition.
3. Collections.synchronizedMap()¶
Java provides:
Map<Integer, String> map =
Collections.synchronizedMap(new HashMap<>());
Internally:
synchronized (mutex) {
map.put(key, value);
}
Only one thread can access the map at a time.
Problem¶
Suppose:
100 threads
Thread 1 → waiting
Thread 2 → waiting
Thread 3 → waiting
Only one proceeds.
Performance suffers significantly under contention.
4. ConcurrentHashMap¶
Designed specifically for concurrent access.
Example:
ConcurrentHashMap<Integer, String> map =
new ConcurrentHashMap<>();
Characteristics:
- Thread-safe
- High throughput
- No global lock
- Excellent scalability
5. Java 7 Implementation¶
Interview question.
Java 7 used segment locking.
Structure:
ConcurrentHashMap
↓
Segment[]
↓
HashEntry[]
Each segment had its own lock.
Example:
Segment 1 → Locked
Segment 2 → Free
Segment 3 → Free
Threads working in different segments proceeded concurrently.
Drawback¶
Too many segments increased memory overhead and added implementation complexity.
6. Java 8 Implementation¶
Java 8 removed segments.
Current structure:
ConcurrentHashMap
↓
Node[]
Similar to HashMap, but with sophisticated concurrency control.
Synchronization occurs per bucket when necessary.
7. CAS (Compare-And-Set)¶
One of the most important interview concepts.
CAS is an atomic CPU-supported operation.
Concept:
Current value = A
Expected = A
New value = B
If the current value is still A:
Replace with B
Otherwise:
Retry
No traditional lock is required.
Example¶
Thread 1:
Expected = 10
Current:
10
CAS:
10 → 20
Success.
Thread 2:
Expected:
10
Current:
20
CAS fails.
Thread 2 retries.
8. Why CAS?¶
Traditional locking:
Acquire lock
↓
Modify
↓
Release lock
CAS:
Try
↓
Success?
↓
Done
↓
Else retry
Advantages:
- Less blocking
- Better scalability
- Higher throughput under light to moderate contention
9. put() in ConcurrentHashMap¶
Simplified flow:
hash
↓
bucket
↓
Empty?
↓
CAS insert
If the bucket is already occupied:
Lock bucket
↓
Modify linked list/tree
↓
Unlock
Only the affected bucket is synchronized.
Other buckets remain accessible.
10. Read Operations¶
Interview favorite.
get() is typically lock-free.
map.get(key);
Readers generally do not block each other or writers (subject to memory visibility guarantees provided by the implementation).
This is a major reason ConcurrentHashMap performs well.
11. Null Keys and Values¶
Unlike HashMap:
ConcurrentHashMap
does not allow:
null key
null value
Reason:
map.get(key)
Returning null must unambiguously mean:
- Key absent
There should be no confusion with:
key -> null
12. Resize¶
Concurrent resizing is coordinated so that multiple threads can assist with transferring buckets.
This avoids one thread becoming a bottleneck.
The implementation is considerably more complex than HashMap.
13. Treeification¶
Exactly like HashMap:
Linked List
↓
Red-Black Tree
when:
- Bucket size ≥ 8
- Table capacity ≥ 64
14. Time Complexity¶
| Operation | Average |
|---|---|
| put | O(1) |
| get | O(1) |
| remove | O(1) |
Worst-case bucket operations remain O(log n) after treeification.
15. CopyOnWriteArrayList¶
Another favorite interview topic.
Designed for:
- Many readers
- Few writers
Example:
CopyOnWriteArrayList<String> list =
new CopyOnWriteArrayList<>();
Write Operation¶
Suppose:
[A B C]
Add:
D
Internally:
Copy array
↓
[A B C D]
↓
Replace reference
Readers continue using the old array until the new one becomes visible.
Advantages¶
- Iteration requires no locking.
- No
ConcurrentModificationException. - Excellent for read-heavy workloads.
Disadvantages¶
Every write copies the entire array.
Writing complexity:
O(n)
16. When to Use CopyOnWriteArrayList¶
Good:
- Configuration data
- Listener lists
- Plugin registries
- Feature flags
Bad:
- Frequent insertions
- Large mutable lists
17. ConcurrentLinkedQueue¶
Implementation:
- Lock-free
- CAS-based
- FIFO
Suitable for:
- High-concurrency message passing
- Task queues
18. BlockingQueue¶
Used in producer-consumer systems.
Example:
BlockingQueue<String> queue =
new LinkedBlockingQueue<>();
Producer:
queue.put(task);
Consumer:
queue.take();
If empty:
Consumer waits.
19. ConcurrentSkipListMap¶
Thread-safe alternative to TreeMap.
Characteristics:
- Sorted
- Concurrent
- O(log n)
Internally:
Skip List
instead of a Red-Black Tree.
20. Skip List¶
Conceptually:
Level 3
↓
Level 2
↓
Level 1
↓
Sorted List
Search skips large portions of the data.
Average:
O(log n)
21. WeakHashMap¶
Interview favorite.
Keys are stored using weak references.
If no strong reference to a key exists:
GC
↓
Entry removed automatically
Useful for:
- Caches
- Metadata associated with objects
22. IdentityHashMap¶
Normal HashMap:
equals()
IdentityHashMap:
==
Example:
String a = new String("Java");
String b = new String("Java");
HashMap:
1 key
IdentityHashMap:
2 keys
because a != b by reference.
23. EnumMap¶
Optimized for enum keys.
Example:
enum Status {
NEW,
RUNNING,
DONE
}
EnumMap<Status, String> map =
new EnumMap<>(Status.class);
Advantages:
- Very fast
- Memory efficient
- Array-backed internally
24. Choosing the Right Concurrent Collection¶
| Requirement | Collection |
|---|---|
| Thread-safe map | ConcurrentHashMap |
| Read-heavy list | CopyOnWriteArrayList |
| FIFO concurrent queue | ConcurrentLinkedQueue |
| Producer-consumer | BlockingQueue |
| Sorted concurrent map | ConcurrentSkipListMap |
| Weak-reference cache | WeakHashMap |
| Enum keys | EnumMap |
Common Interview Questions¶
Q1. Why is HashMap not thread-safe?¶
Because concurrent modifications can corrupt its internal state and it performs no synchronization.
Q2. Why not always use Collections.synchronizedMap()?¶
It uses a single lock, reducing concurrency and scalability.
Q3. Difference between Java 7 and Java 8 ConcurrentHashMap?¶
| Java 7 | Java 8 |
|---|---|
| Segment locking | Bucket-level synchronization + CAS |
| More memory overhead | Lower overhead |
| More complex structure | Simpler Node[]-based design |
Q4. Why is get() fast?¶
Reads are generally lock-free.
Q5. Why are nulls not allowed?¶
To avoid ambiguity between:
- Key not present
- Key mapped to
null
Q6. When should you use CopyOnWriteArrayList?¶
When reads vastly outnumber writes.
Q7. What is CAS?¶
An atomic compare-and-update operation that reduces the need for locks.
Q8. Which concurrent map maintains sorted order?¶
ConcurrentSkipListMap
Q9. Difference between TreeMap and ConcurrentSkipListMap?¶
| TreeMap | ConcurrentSkipListMap |
|---|---|
| Not thread-safe | Thread-safe |
| Red-Black Tree | Skip List |
| O(log n) | O(log n) |
Q10. What would you use for a cache?¶
It depends:
- Simple concurrent cache →
ConcurrentHashMap - Cache requiring automatic eviction of entries whose keys are no longer referenced →
WeakHashMap - Production caches with expiration, size limits, and statistics → libraries such as Caffeine (commonly used in modern Java applications)
Senior Interview Scenario¶
Question:
Your application has:
- 500 reader threads
- 5 writer threads
Should you use:
Collections.synchronizedMap()ConcurrentHashMap
Expected Answer:
ConcurrentHashMap.
Reason:
- Readers generally proceed without blocking.
- Writes synchronize only where necessary.
- Throughput scales much better than a single global lock.
Key Takeaways¶
HashMapis not thread-safe.ConcurrentHashMapis the standard concurrent map implementation.- Java 8 replaced segment locking with bucket-level synchronization and CAS.
- CAS enables many operations without traditional locking.
CopyOnWriteArrayListis ideal for read-heavy workloads.BlockingQueueis fundamental for producer-consumer designs.ConcurrentSkipListMapprovides thread-safe sorted maps.WeakHashMap,IdentityHashMap, andEnumMapsolve specialized problems.
Next: Part 9 — Iterators Deep Dive¶
We'll cover:
IteratorListIteratorEnumeration- Fail-fast vs fail-safe iterators
modCountConcurrentModificationException- Safe element removal during iteration
- Internal implementation and interview questions