I have a Map which is to be modified by several threads concurrently.
There seem to be three different synchronized Map implementations in the Java API:
Hashtable and ConcurrentHashMap do not allow null
keys or null
values.
Collections.synchronizedMap(Map) synchronizes all operations (get
, put
, size
, etc).
ConcurrentHashMap supports full concurrency of retrievals, and adjustable expected concurrency for updates.
As usual, there are concurrency--overhead--speed tradeoffs involved. You really need to consider the detailed concurrency requirements of your application to make a decision, and then test your code to see if it's good enough.
Synchronized Map:
Synchronized Map is also not very different than Hashtable and provides similar performance in concurrent Java programs. Only difference between Hashtable and SynchronizedMap is that SynchronizedMap is not a legacy and you can wrap any Map to create it’s synchronized version by using Collections.synchronizedMap() method.
ConcurrentHashMap:
The ConcurrentHashMap class provides a concurrent version of the standard HashMap. This is an improvement on the synchronizedMap functionality provided in the Collections class.
Unlike Hashtable and Synchronized Map, it never locks whole Map, instead it divides the map in segments and locking is done on those. It perform better if number of reader threads are greater than number of writer threads.
ConcurrentHashMap by default is separated into 16 regions and locks are applied. This default number can be set while initializing a ConcurrentHashMap instance. When setting data in a particular segment, the lock for that segment is obtained. This means that two updates can still simultaneously execute safely if they each affect separate buckets, thus minimizing lock contention and so maximizing performance.
ConcurrentHashMap doesn’t throw a ConcurrentModificationException
ConcurrentHashMap doesn’t throw a ConcurrentModificationException if one thread tries to modify it while another is iterating over it
Difference between synchornizedMap and ConcurrentHashMap
Collections.synchornizedMap(HashMap) will return a collection which is almost equivalent to Hashtable, where every modification operation on Map is locked on Map object while in case of ConcurrentHashMap, thread-safety is achieved by dividing whole Map into different partition based upon concurrency level and only locking particular portion instead of locking whole Map.
ConcurrentHashMap does not allow null keys or null values while synchronized HashMap allows one null keys.
Similar links
Link1
Link2
Performance Comparison
╔═══════════════╦═══════════════════╦═══════════════════╦═════════════════════╗
║ Property ║ HashMap ║ Hashtable ║ ConcurrentHashMap ║
╠═══════════════╬═══════════════════╬═══════════════════╩═════════════════════╣
║ Null ║ allowed ║ not allowed ║
║ values/keys ║ ║ ║
╠═══════════════╬═══════════════════╬═════════════════════════════════════════╣
║ Thread-safety ║ ║ ║
║ features ║ no ║ yes ║
╠═══════════════╬═══════════════════╬═══════════════════╦═════════════════════╣
║ Lock ║ not ║ locks the whole ║ locks the portion ║
║ mechanism ║ applicable ║ map ║ ║
╠═══════════════╬═══════════════════╩═══════════════════╬═════════════════════╣
║ Iterator ║ fail-fast ║ weakly consistent ║
╚═══════════════╩═══════════════════════════════════════╩═════════════════════╝
Regarding locking mechanism:
Hashtable
locks the object, while ConcurrentHashMap
locks only the bucket.
In ConcurrentHashMap
, the lock is applied to a segment instead of an entire Map.
Each segment manages its own internal hash table. The lock is applied only for update operations. Collections.synchronizedMap(Map)
synchronizes the entire map.
The main difference between these two is that ConcurrentHashMap
will lock only portion of the data which are being updated while other portion of data can be accessed by other threads. However, Collections.synchronizedMap()
will lock all the data while updating, other threads can only access the data when the lock is released. If there are many update operations and relative small amount of read operations, you should choose ConcurrentHashMap
.
Also one other difference is that ConcurrentHashMap
will not preserve the order of elements in the Map passed in. It is similar to HashMap
when storing data. There is no guarantee that the element order is preserved. While Collections.synchronizedMap()
will preserve the elements order of the Map passed in. For example, if you pass a TreeMap
to ConcurrentHashMap
, the elements order in the ConcurrentHashMap
may not be the same as the order in the TreeMap
, but Collections.synchronizedMap()
will preserve the order.
Furthermore, ConcurrentHashMap
can guarantee that there is no ConcurrentModificationException
thrown while one thread is updating the map and another thread is traversing the iterator obtained from the map. However, Collections.synchronizedMap()
is not guaranteed on this.
There is one post which demonstrate the differences of these two and also the ConcurrentSkipListMap
.
ConcurrentHashMap is preferred when you can use it - though it requires at least Java 5.
It is designed to scale well when used by multiple threads. Performance may be marginally poorer when only a single thread accesses the Map at a time, but significantly better when multiple threads access the map concurrently.
I found a blog entry that reproduces a table from the excellent book Java Concurrency In Practice, which I thoroughly recommend.
Collections.synchronizedMap makes sense really only if you need to wrap up a map with some other characteristics, perhaps some sort of ordered map, like a TreeMap.