ConcurrentHashMap
About
ConcurrentHashMap
is a thread-safe, high-performance implementation of the Map
interface introduced in Java 1.5 as part of the java.util.concurrent
package. It allows concurrent read and write operations without explicit synchronization. Unlike HashMap
, which is not thread-safe, and Hashtable
, which synchronizes the entire map, ConcurrentHashMap
employs advanced concurrency techniques to ensure high efficiency.
Features
Thread-Safe: Allows multiple threads to read and write concurrently.
No Null Keys or Values: Unlike
HashMap
,ConcurrentHashMap
does not allownull
keys or values.Segmented Locking: Divides the map into segments to reduce contention during updates.
High Performance: Better performance than
Hashtable
for concurrent operations.Non-Blocking Reads: Uses volatile fields and CAS (Compare-And-Swap) for faster reads.
Partial Synchronization: Only updates on specific segments are synchronized, not the entire map.
Internal Working
Data Structure
The
ConcurrentHashMap
in Java 8 uses an array ofNode<K,V>
objects (called buckets) as the base structure.Each bucket may contain a chain of nodes (linked list) or a balanced red-black tree when the bucket size exceeds a threshold (usually 8 elements). This improves search time from O(n)O(n) to O(logn)O(logn).
Concurrency Mechanism
Instead of segment-level locking (used in Java 7), Java 8 employs bucket-level locks.
The locking mechanism uses:
CAS operations for most operations, ensuring lock-free updates.
Synchronized blocks for updates when contention occurs, reducing overhead compared to segment locks.
CAS Operations
CAS ensures atomicity during updates, such as inserting or updating elements. The
Unsafe
class is used to implement CAS.Example: During put operations, the
compareAndSwap
method is used to add a node if the bucket is empty.
Treeification
When the number of nodes in a bucket exceeds 8 (threshold), the bucket transitions into a red-black tree to maintain O(logn)O(logn) performance for lookups.
If the size of the tree shrinks below 6, it reverts back to a linked list.
Resizing
Resizing occurs when the number of elements exceeds the load factor (default: 0.75).
Resizing doubles the table size and redistributes elements across new buckets.
The process uses lazy transfer:
A resize task is distributed across multiple threads for better performance.
Threads work on splitting the old buckets into the new ones, avoiding a single-thread bottleneck.
Locking on Updates
For updates (like put or remove) on a bucket that already has entries, a synchronized block ensures mutual exclusion.
This localized locking avoids global locks and allows high concurrency.
Read Operations
Read operations (
get
,containsKey
) are lock-free:They traverse the bucket (linked list or tree) directly.
As reads don't block, high concurrency is achieved for reading data.
Thread-Safety
The combination of CAS and synchronized blocks ensures thread-safe access to the map without significant contention.
This architecture allows multiple threads to operate on different buckets simultaneously without locking the entire map.
Key Methods
Method
Description
put(K key, V value)
Associates the specified value with the key.
get(Object key)
Retrieves the value for the specified key.
remove(Object key)
Removes the mapping for the specified key.
containsKey(Object key)
Checks if the map contains the specified key.
containsValue(Object value)
Checks if the map contains the specified value.
replace(K key, V oldValue, V newValue)
Replaces the old value with a new value if the key is present.
computeIfAbsent(K key, Function<K,V>)
Computes the value if the key is not already associated with one.
compute(K key, BiFunction<K,V,V>)
Updates the value for a key using the provided function.
forEach()
Performs the given action for each entry in the map.
merge(K key, V value, BiFunction<V,V,V>)
Merges the given value with the existing value for the specified key.
Big-O for Operations
Operation
Average Case
Worst Case
Put
O(1)
O(n)
Get
O(1)
O(n)
Remove
O(1)
O(n)
Iteration
O(n)
O(n)
Limitations
No Null Keys or Values: Does not support
null
keys or values to prevent ambiguity in concurrent environments.Higher Memory Usage: Segments and internal structures may increase memory overhead compared to
HashMap
.Iteration Limitations: Iterators are weakly consistent and do not reflect real-time changes.
Real-World Usage
Caching Systems: Used in concurrent caches to store frequently accessed data.
Thread-Safe Data Structures: Ideal for multithreaded applications that need a shared map.
Concurrent Algorithms: Used in scenarios requiring concurrent lookups and updates, such as real-time analytics or monitoring.
Examples
1. Basic Operations
2. Concurrent Access
3. Real-Time Analytics
Last updated
Was this helpful?