Monday, May 30, 2016

ConcurrentHashMap vs Hashtable vs Synchronized Map


v ConcurrentHashMap performs better than earlier two because it only locks a portion of Map, instead of whole Map, which is the case with Hashtable and synchronized Map.

v CHM allows concurred read operations and same time, maintains integrity by synchronizing write operations. 

v ConcurrentHashMap is best suited when you have multiple readers and few writers. 

v During update operation, ConcurrentHashMap only lock a portion of Map instead of whole Map.
"Concurrency level", allows ConcurrentHashMap to partition Map.

v ConcurrentHashMap partitions Map into different parts based on concurrency level and locking only a portion of Map during updates. Default concurrency level is 16, and accordingly Map is divided into 16 part and each part is governed with different lock. This means, 16 thread can operate on Map simultaneously, until they are operating on different part of Map. This makes ConcurrentHashMap high performance despite keeping thread-safety intact. 

v Another important point to remember is iteration over CHM, Iterator returned by keySet of ConcurrentHashMap are weekly consistent and they only reflect state of ConcurrentHashMap and certain point and may not reflect any recent change. Iterator of ConcurrentHashMap's keySet area also fail-safe and doesn’t throw ConcurrentModificationExceptoin.

v Default concurrency level is 16 and can be changed.

v ConcurrentHashMap doesn't allow null as key or value.

v ConcurrentHashMap provides putIfAbsent(key, value) which does same thing but atomically and thus eliminates below race condition.

synchronized(map){
  if (map.get(key) == null){
      return map.put(key, value);
  } else{
      return map.get(key);
  }
}

HashMap
Collections.SynchronizedMap
ConcurrentHashMap
No Synchronization
Use very simple synchronization, which means that only one thread can access the map at the same time.
Allow parallel read access by multiple threads without synchronization and, more importantly, provides an Iterator that requires no synchronization and even allows the Map to be modified during interation
Null key-value pair allowed
No Null Key-value pair
No Null Key-value pair
No Lock Mechanism . HashTable locks the object
Locks the whole map
Locks the segment out of 16 segments. Locks bucket only
Not thread-Safe
Thread-Safe
Thread-Safe
Fail-fast Iterator
Fail-fast Iterator
Fail-safe Iterator

Why Concurrent HashMap doesn’t allow null key ?

The main reason that nulls aren't allowed in ConcurrentMaps (ConcurrentHashMaps, ConcurrentSkipListMaps) because there will be ambiguities that may be just barely tolerable in non-concurrent maps can't be accommodated.

The main one is that if map.get(key) returns null, you can't detect whether the key explicitly maps to null vs the key isn't mapped.

if (key == null || value == null) throw new NullPointerException();
public class ConcurrentHashMapDemo {

     public static void main(String[] args) {
           ConcurrentHashMap<String, String> chm= new ConcurrentHashMap<>();
           chm.put(null,"Paras");
           System.out.println(chm.get(null));
     }
}

Output:

Exception in thread "main" java.lang.NullPointerException
at java.util.concurrent.ConcurrentHashMap.putVal(Unknown Source)
at java.util.concurrent.ConcurrentHashMap.put(Unknown Source)
at com.javadsalgo.ConcurrentHashMapDemo.main(ConcurrentHashMapDemo.java:9)

In a non-concurrent map, you can check this via map.contains(key), but in a concurrent one, the map might have changed between calls.

The code is like this :

    
if (map.containsKey(k)) {
     return map.get(k);
else {
     throw new KeyNotPresentException();
}

It might be possible that key k might be deleted in between the get(k) and containsKey(k) calls.
As a result, the code will return null as opposed to KeyNotPresentException (Expected Result if key is not present).


The Null key and value allowed in HashMap because there is no Concurrent access.

No comments:

Post a Comment