ConcurrentHashMap in Java

Though we have thread-safe collections classes like HashTable, Synchronized Map, which can be used in multi-threaded environment but there are significant differences between them, which arise from the fact that how they achieve their thread-safety.

All methods of Hashtable are synchronized which make them quite slow due to the number of thread increases. Synchronized Map is also similar to the Hashtable and provides similar performance in concurrent environments. Synchronized Map can be achieved by using Collections.synchronizedMap() method.

You can check How HashMap works in java

ConcurrentHashMap is specially designed for use in concurrent environment where multiple threads can be used to access the map. By default it simultaneously allows 16 threads to read and write from Map without any external synchronization.

ConcurrentHashMap was introduced as an alternative of HashTable with same functional specifications as the HashTable has but with high expected concurrency for updates. Though all operations are thread-safe in ConcurrentHashMap but retrieval operations do not involve in locking; so the entire table is not locked to prevent entire access. As the retrieval operations do not lock so it may overlap with update operations. Retrieval operations reflect the results of most recently completed update operations because an update operation for a given key bears a happens-before relation with any non-null retrieval for that key reporting the update value. So any non-null result returned from get(key) and related access methods bears a happens-before relation with the associated insertion or update.

Features of ConcurrentHashMap
The ConcurrentHashMap does not throw ConcurrentModificationException.
Like Hashtable but unlike HashMap, this class does not allow null to be used as a key or value.

It supports a set of sequential and parallel bulk operations that are designed to be safely even when being concurrently updated by other threads.

The elements of a ConcurrentHashMap are not ordered in any particular way and may be processed in different orders in different parallel executions. Hence the correctness of supplied functions should not depend on any ordering, or on any other objects or values that may transiently change while computation is in progress.

Why do we need ConcurrentHashMap

The synchronized collections class HashTable and the synchronized wrapper class Collections.synchronizedMap() provide a basic conditionally thread-safe implementations of Map. However, several factors make them unsuitable for use in highly concurrent applications, for example, their single collection-wide lock is a limitation to the scalability and it often becomes necessary to lock a collection for a considerable time during iteration to prevent ConcurrentModificationException.

ConcurrentHashMap implementations provide much higher concurrency while preserving thread safety, with some minor compromises in their promises to callers. ConcurrentHashMap is not necessarily useful everywhere you might use HashMap, but is designed to optimize specific common situations. Many concurrent applications will benefit from their use.

Operations on ConcurrentHashMap
forEach: performs a given action on each element.
search: returns the first available non-null result of applying a given function on each element while skipping further search when a result is found.
reduce: accumulates each element.
There are five variants:

Plain reductions where there is no form of this method available for (key, value) function arguments since there is no corresponding return type.)
Mapped reductions that accumulate the results of a given function applied to each element.
Reductions to scalar doubles, longs, and ints, using a given basis value.

Summary

ConcurrentHashMap shoulde be used when very high concurrency is required in a project.
It is thread safe without synchronizing the whole map, instead, it divides the map into segments and locking is done on those.
Read happens very fast while write is done with a lock.
There is no locking at the object level.
The locking is at a much finer granularity at a hashmap Bucket level.
ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to modify the map while another is iterating over it.

Example

Create the below ConcurrentHashMapExample class. In this example, you find I have used puIfAbsent() method that puts an element into the map for a given key if the key already does not exist. I have used here Java 8 forEach loop to iterate over the map.

package com.roytuts.collections;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
public class ConcurrentHashMapExample {
    public static void main(String[] args) {
        ConcurrentMap<String, String> cMap = new ConcurrentHashMap<>();
        cMap.put("RedHat", "Unix");
        cMap.put("Google", "Android");
        cMap.put("Apple", "iOS");
        cMap.put("Microsoft", "Windows");
        cMap.putIfAbsent("RedHat", "Unix");
        cMap.forEach((k, v) -> System.out.println(k + " => " + v));
    }
}

Output

RedHat => Unix
Google => Android
Apple => iOS
Microsoft => Windows

Thanks for reading.

Leave a Reply

Your email address will not be published. Required fields are marked *