Master java skills

ConcurrentHashMap in Java

CosurrentHashMap, as its name suggests, provides concurrent access to multiple threads. It is thread safe version of HashMap. We know, HashMap is not synchronized and therefore is not thread safe. To overcome this issue, collections framework provides ConcurrentHashMap.

ConcurrentHashMap provides similar functionalities like HashMap. The only difference is that it internally maintains concurrency.
It is concurrent version of HashMap. It internally maintains a HashTable, which is divided into segments. The number of segments depend on the level of concurrency specified in the ConcurrentHashMap. By default, it divides it into 16 segments. It doesn’t lock the entire map unlike HashTable or Synchronized HashMap. It only locks the particular segment of HashMap where write operation is going on.

Class declaration

class ConcurrentHashMap<K,V> extends AbstractMap<K,V> implements ConcurrentMap<K,V>, Serializable

Class hierarchy

Constructors summary

ConcurrentHashMap()            //default constructor
ConcurrentHashMap(Map<? extends K, ? extends V> m)
ConcurrentHashMap(int initialCapacity, float loadFactor)
ConcurrentHashMap(int initialCapacity, float loadFactor, int concurrencyLevel)

Features of ConcurrentHashMap

  1. ConcurrentHashMap internally uses HashTable as its data structure. It is thread safe just like Hashtable. It provides all the functionalities of HashMap except thread safety.
  2. ConcurrentHashMap internally divides it into segments. Each segment works independently and can be accessed by different reader threads simultaneously. However, each segment can be accessed only by one writer thread at a time. This also means, a concurrent hash map can be accessed by as many writer threads together as there are segments.
  3. The default level of concurrency is 16. Which means by default, there are 16 segments.
  4. Read operations don’t require locking of cocurrent hash map, where as write operations do require locking.
  5. Locking is known as segment or bucket locking.
  6. Concurrent hash map doesn’t allow null key or null values.

ConcurrentHashmap code example

package com.javatrainingschool;

import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
	
	public static void main(String[] args) {
		
		ConcurrentHashMap<Integer, String> cMap = new ConcurrentHashMap<>();
		cMap.put(1, "Taj Mahal");
		cMap.put(2, "Qutab Minar");
		cMap.put(3, "Char Minar");
		
		for(Integer key : cMap.keySet()) {
			System.out.println(key + " : " + cMap.get(key));
		}
	}
}
Output :
1 : Taj Mahal
2 : Qutab Minar
3 : Char Minar

Concurrent modification in ConcurrentHashMap

ConcurrentHashMap returns a fail safe iterator. It means, using this iterator, we can modify ConcurrentHashMap while iterating it. Let’s see one example

package com.javatrainingschool;

import java.util.Iterator;
import java.util.concurrent.ConcurrentHashMap;

public class ConcurrentHashMapExample {
	
	public static void main(String[] args) {
		
		ConcurrentHashMap<Integer, String> cMap = new ConcurrentHashMap<>();
		cMap.put(1, "Taj Mahal");
		cMap.put(2, "Qutab Minar");
		cMap.put(3, "Char Minar");
		
		Iterator<Integer> it = cMap.keySet().iterator();
		while(it.hasNext()) {
			int key = it.next();
			if(key == 2)
				cMap.put(2, "Gateway of India");
			System.out.println(key + " : " + cMap.get(key));
		}
	}
}
Output :
1 : Taj Mahal
2 : Gateway of India
3 : Char Minar

Fail safe iterator returned by ConcurrentHashMap

In the above example, we saw that we can modify ConcurrentHashMap while iterating it. It became possible because the iterator returned by ConcurrentHashMap is fail safe. Which means we can modify it while iterating.

Internal working of ConcurrentHashMap

ConcurrentHashMap performs segment locking in a multithreading environment. It allows performing read operations concurrently without any blocking of threads.
It performs retrieval operations without blocking but write operations may conflict each other if they are working on the same segment. Each segment works as an individual HashMap. So, if one thread is writing onto one segment, it locks that segment. Now until that thread is done, no other thread will get access to that segment. However, reader threads can still access this segement. If another thread, wants to write to another segment at the same time, it is free to do so. It will acquire lock on that segment and will start doing its job.
Read operations return most recently updated operations, which means the it may not fetch the currently updating value.
Memory visibility for the read operations is ensured by volatile reads.