Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Collections.synchronizedMap(new LinkedHashMap()); is not making Map threadsafe

I'm using following construct for creating a threadsafe Map.

Collections.synchronizedMap(new LinkedHashMap());

Though I'm getting ConcurrentModificationException error.

like image 219
krishna Avatar asked Oct 31 '12 04:10

krishna


People also ask

What is the difference between HashMap ConcurrentHashMap and a Map returned by collections synchronizedMap?

1 Answer. ConcurrentHashMap is designed for concurrency and improves performance while Collections. synchronizedMap(map) which is non-synchronized by sort can be synchronized by applying a wrapper using Collections.

Is synchronized Map thread-safe?

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.

How do you make a Map synchronized?

A synchronized resource can be accessed by only one thread at a time. HashMap can be synchronized using the Collections. synchronizedMap() method. The synchronizedMap() method of java.

Which is better to use synchronized over the Map or using ConcurrentHashMap?

ConcurrentHashMap allows performing concurrent read and write operation. Hence, performance is relatively better than the Synchronized Map. In Synchronized HashMap, multiple threads can not access the map concurrently. Hence, the performance is relatively less than the ConcurrentHashMap.


3 Answers

Without code it is hard to guess what is the real issue, but my guess is, you are not using returned collection to perform operations. As per javadoc

In order to guarantee serial access, it is critical that all access to the backing collection is accomplished through the returned collection. It is imperative that the user manually synchronize on the returned collection when iterating over it:

  Collection c = Collections.synchronizedCollection(myCollection);
     ...
  synchronized(c) {
      Iterator i = c.iterator(); // Must be in the synchronized block
      while (i.hasNext())
         foo(i.next());
  }

Failure to follow this advice may result in non-deterministic behavior.

like image 138
kosa Avatar answered Oct 28 '22 05:10

kosa


Not to detract from any of the other answers here, but this code below shows that concurrent modification has little to do with actual multithreading. It's caused when you say, iterate over a collection but modify it while you are iterating....

  List list = new ArrayList();
  list.add("1");
  list.add("2");

  Iterator i = list.iterator();
  while (i.hasNext()) {
      Object value = i.next();  // throws java.util.ConcurrentModificationException

      list.add("another");  
  }
like image 23
slipperyseal Avatar answered Oct 28 '22 06:10

slipperyseal


Long story short, the solution to not get a ConcurrentModificationException in your code would be using a ConcurrentHashMap instead of Collections.synchronizedMap(new LinkedHashMap());. Explanation here:

  • What's the difference between ConcurrentHashMap and Collections.synchronizedMap(Map)?

As Nambari says, the problem is harder to identify without actual code. Note that this Map only protects the objects that contains. Still, you can modify a same object instance in a method:

Map<String, Object> map = new ConcurrentHashMap<String, Object();
//fill the map...
map.put("data", new Data());

//and now we have this unsynchronized method that two or more threads can access at the same time
public void modifyData(String key, int newDataIntValue) {
    //this is synchronized by the ConcurrentHashMap
    Data data = map.get(key);
    //this isn't
    //you can get problems here...
    data.setIntValue(newDataIntValue);
}

The synchronized collection won't save your code for these cases. You should synchronize this method by yourself.

Additional info: if you're trying to implement a cache library or the Flyweight design pattern, don't reinvent the wheel and use a proven and tested framework like ehcache or jboss cache.

like image 36
Luiggi Mendoza Avatar answered Oct 28 '22 04:10

Luiggi Mendoza