What is the difference between using the wrapper class, SynchronizedMap, on a HashMap and ConcurrentHashMap?
Is it just being able to modify the HashMap while iterating it (ConcurrentHashMap)?
What is the difference between using the wrapper class, SynchronizedMap, on a HashMap and ConcurrentHashMap?
Is it just being able to modify the HashMap while iterating it (ConcurrentHashMap)?
Synchronized HashMap:
Each method is synchronized using an object level lock. So the get and put methods on synchMap acquire a lock.
Locking the entire collection is a performance overhead. While one thread holds on to the lock, no other thread can use the collection.
ConcurrentHashMap was introduced in JDK 5.
There is no locking at the object level,The locking is at a much finer granularity. For a ConcurrentHashMap, the locks may be at a hashmap bucket level.
The effect of lower level locking is that you can have concurrent readers and writers which is not possible for synchronized collections. This leads to much more scalability.
ConcurrentHashMap does not throw a ConcurrentModificationException if one thread tries to modify it while another is iterating over it.
This article Java 7: HashMap vs ConcurrentHashMap is a very good read. Highly recommended.
SynchronizedMap and ConcurrentHashMap are both thread safe class and can be used in multithreaded application, the main difference between them is regarding how they achieve thread safety.
SynchronizedMap acquires lock on the entire Map instance , while ConcurrentHashMap divides the Map instance into multiple segments and locking is done on those.
A simple performance test for ConcurrentHashMap vs Synchronized HashMap
. The test flow is calling put in one thread and calling get in three threads on Map concurrently. As @trshiv said, ConcurrentHashMap has higher throughput and speed for whose reading operation without lock. The result is when operation times is over 10^7, ConcurrentHashMap is 2x faster than Synchronized HashMap.
Synchronized HashMap
2.Null key or Value - It will allow null as a key or value.
3.Concurrent modification exception - Iterator return by synchronized map throws concurrent modification exception
ConcurrentHashMap
1.Lock mechanism -Locks the portion, Concurrent hashmap allows concurrent read and write. So performance is relatively better than a synchronized map
2.Null key or Value - It doesn't allow null as a key or value. If you use it will throw java.lang.NullPointerException at Runtime.
3.Concurrent modification exception - It doesn't throw concurrent modification exceptions.
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class Ex_ConcurrentHashMap {
public static void main(String[] args) {
Map<String, String> map = new ConcurrentHashMap<>();
map.put("one", "one");
map.put("two", "two");
map.put("three", "three");
System.out.println("1st map : "+map);
String key = null;
for(Map.Entry<String, String> itr : map.entrySet())
{
key = itr.getKey();
if("three".equals(key))
{
map.put("FOUR", "FOUR");
}
System.out.println(key+" ::: "+itr.getValue());
}
System.out.println("2nd map : "+map);
//map.put("FIVE", null);//java.lang.NullPointerException
map.put(null, "FIVE");//java.lang.NullPointerException
System.out.println("3rd map : "+map);
}
}
Synchronized HashMap Example
import java.util.Collections;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
public class Ex_Synchronizedmap {
public static void main(String[] args) {
Map<String, String> map = new HashMap<>();
map.put("one", "one");
map.put("two", "two");
map.put("three", "three");
map.put("FOUR", null);
map.put(null, "FIVE");
System.out.println("map : "+map);
Map<String, String> map1 =
Collections.synchronizedMap(map);
System.out.println("map1 : "+map1);
String key = null;
for(Map.Entry<String, String> itr : map1.entrySet())
{
key = itr.getKey();
if("three".equals(key))
{
map1.put("ABC", "ABC");
}
System.out.println(key+" ::: "+itr.getValue());
}
System.out.println("New Map :: "+map1);
Iterator<Entry<String, String>> iterator = map1.entrySet().iterator();
int i = 0;
while(iterator.hasNext())
{
if(i == 1)
{
map1.put("XYZ", "XYZ");
}
Entry<String, String> next = iterator.next();
System.out.println(next.getKey()+" :: "+next.getValue());
i++;
}
}
}
As per java doc's
Hashtable and Collections.synchronizedMap(new HashMap()) are synchronized. But ConcurrentHashMap is "concurrent".
A concurrent collection is thread-safe, but not governed by a single exclusion lock.
In the particular case of ConcurrentHashMap, it safely permits any number of concurrent reads as well as a tunable number of concurrent writes. "Synchronized" classes can be useful when you need to prevent all access to a collection via a single lock, at the expense of poorer scalability.
In other cases in which multiple threads are expected to access a common collection, "concurrent" versions are normally preferable. And unsynchronized collections are preferable when either collections are unshared, or are accessible only when holding other locks.