The ConcurrentHashMap is very similar to the
HashMap class, except that ConcurrentHashMap offers internally maintained
concurrency. It means you do not need to have synchronized blocks when
accessing ConcurrentHashMap in multithreaded application.
The
only thread safe collection objects were Hashtable and synchronized Map prior
to JDK 5.
Why
we need ConcurrentHashMap when we already had Hashtable?
HashTable allows us to access Map.Entries objects by locking the entire map, may it be a read or update or delete. Which means thread wait time to perform an operation on HashTable is longer. This leads to an overhead when we have a heavily loaded application.
ConcurrentHashMap resolves this issue by not obtaining lock on the entire map, but locking the segments.
HashTable allows us to access Map.Entries objects by locking the entire map, may it be a read or update or delete. Which means thread wait time to perform an operation on HashTable is longer. This leads to an overhead when we have a heavily loaded application.
ConcurrentHashMap resolves this issue by not obtaining lock on the entire map, but locking the segments.
How ConcurrentHashMap works in Java
According to ConcurrentHashMap Oracle docs,
The constructor of ConcurrentHashMap looks like this :
public ConcurrentHashMap (int initialCapacity, float loadFactor, int concurrencyLevel)
The
constructor of ConcurrentHashMap uses the below three parameters:
initialCapacity – the initial capacity. The implementation performs internal sizing to accommodate this many elements.
loadFactor – the load factor threshold, used to control resizing. Resizing may be performed when the average number of elements per bin exceeds this threshold.
concurrencyLevel – the estimated number of concurrently updating threads. The implementation performs internal sizing to try to accommodate this many threads.
initialCapacity – the initial capacity. The implementation performs internal sizing to accommodate this many elements.
loadFactor – the load factor threshold, used to control resizing. Resizing may be performed when the average number of elements per bin exceeds this threshold.
concurrencyLevel – the estimated number of concurrently updating threads. The implementation performs internal sizing to try to accommodate this many threads.
The
default value of initialCapacity and concurrencyLevel is 16. Which means
ConcurrentHashMap has 16 locks by default which is acquired on 16 buckets. If
one thread acquired a lock on one bucket, we can have 16 concurrent threads
working on one ConcurrentHashMap at the same time. It doesn’t lock the entire
map. As per Javadocs, retrieval operations do not entail locking, and there is
not any support for locking the entire table in a way that prevents all access.
Can two threads update the ConcurrentHashMap simultaneously?
Yes it is possible that two threads can simultaneously write on the ConcurrentHashMap. ConcurrentHashMap default implementation allows 16 threads to read and write in parallel.
But in the worst case scenario, when two objects lie in the same segment or same partition, then parallel write would not be possible.
Does
ConcurrentHashMap Iterator behave like fail fast iterator or fail safe
Iterator?
ConcurrentHashMap iterator behaves like fail safe iterator. It will not throw ConcurrentModificationException.
ConcurrentHashMap iterator behaves like fail safe iterator. It will not throw ConcurrentModificationException.
Can
multiple threads read from the Hashtable concurrently?
No multiple threads cannot read simultaneously from Hashtable. Reason, the get() method of Hashtable is synchronized. As a result, at a time only one thread can access the get() method .
It is possible to achieve full concurrency for reads (all the threads read at the same time) in ConcurrentHashMap by using volatile keyword.
But, when multiple threads access this, this won’t work as expected.
For this, ConcurrentHashMap provides a putIfAbsent() method that associates the key with a value if not already associated.
No multiple threads cannot read simultaneously from Hashtable. Reason, the get() method of Hashtable is synchronized. As a result, at a time only one thread can access the get() method .
It is possible to achieve full concurrency for reads (all the threads read at the same time) in ConcurrentHashMap by using volatile keyword.
Drawbacks of ConcurrentHashMap
ConcurrentHashMap
doesn’t lock the entire collection while performing modification. So, it may
not provide accurate information about its size using size() operation.
putIfAbsent() method in ConcurrentHashMap
putIfAbsent() method in ConcurrentHashMap
If
a key is not associated with a value, it can be associated with a value with
following logic :
if
(!map.containsKey(key))
return map.put(key, value);
else
return map.get(key);
But, when multiple threads access this, this won’t work as expected.
For this, ConcurrentHashMap provides a putIfAbsent() method that associates the key with a value if not already associated.
replace() method in ConcurrentHashMap
If
we need to replace the value for an existing key, we can normally do so with
following code :
if (map.containsKey(key)) {
return map.put(key, value);
}
However,
in multithreaded environment, this can lead to race condition.
For this, ConcurrentHashMap provides a method replace() to replace the value for an existing key.
We can use it as follows : map.replace(key, value);
For this, ConcurrentHashMap provides a method replace() to replace the value for an existing key.
We can use it as follows : map.replace(key, value);
Summary of ConcurrentHashMap features
·
ConcurrentHashMap is similar to Hashtable,
but performs better in a multi-threaded environment as it does not block itself
to be access by a single thread.
·
It does not allow duplicate keys.
·
It does not allow null to be used as a key
or value.
·
Iterators of ConcurrentHashMap don’t throw
a ConcurrentModificationException, so we don’t need to lock the collection
while iterating it.
No comments:
Post a Comment