ConcurrentHashMap allow concurrent access to the map. The point is to provide an implementation of
HashMap that is
threadsafe. Multiple threads can read from and write to it without the chance of receiving out-of-date or corrupted data.
ConcurrentHashMap provides its own synchronization, so you do not have to synchronize accesses to it explicitly.
The logic behind ConcurrentHashMap is that your entire table is not getting locked, but only the
portion[segments]. Each segments manages its own HashTable. Locking is applied only for updates. In case of of retrievals, it allows full concurrency.
HashTables too offers synchronized access to map, but your entire map is locked to perform any operation.
Another feature of ConcurrentHashMap is that it provides the putIfAbsent method, which will atomically add a mapping if the specified key does not exist. Consider the following code:
myMap.putIfAbsent("key", 3);
- Multiple partitions which can be locked independently. (16 by default)
- Using concurrent Locks operations for thread safety instead of synchronized.
- Has thread safe Iterators. synchronizedCollection's iterators are not thread safe.
- Does not expose the internal locks. synchronizedCollection does.
Let's take four threads are concurrently working on a map whose capacity is 32, the table is partitioned into four segments where each segments manages a hash table of capacity. The collection maintains a list of 16 segments by default, each of which is used to guard (or lock on) a single bucket of the map.
This effectively means that 16 threads can modify the collection at a single time. This level of concurrency can be increased using the optional concurrencyLevel constructor argument.
public ConcurrentHashMap(int initialCapacity,
float loadFactor, int concurrencyLevel)
As the other answer stated, the ConcurrentHashMap offers new method putIfAbsent() which is similar to put except the value will not be overridden if the key exists.
private static Map<String,String> aMap =new ConcurrentHashMap<String,String>();
if(!aMap.contains("key"))
aMap.put("key","value");
The new method is also faster as it avoids double traversing as above. contains method has to locate the segment and iterate the table to find the key and again the method put has to traverse the bucket and put the key.