6

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

Collections.synchronizedMap(new LinkedHashMap());

Though I'm getting ConcurrentModificationException error.

Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
krishna
  • 61
  • 1
  • 2

5 Answers5

8

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.

kosa
  • 65,990
  • 13
  • 130
  • 167
  • 3
    The problem would be avoided by using a `ConcurrentHashMap` instead of `Collections.synchronizedCollection(myCollection);`. – Luiggi Mendoza Oct 31 '12 at 04:20
5

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");  
  }
slipperyseal
  • 2,728
  • 1
  • 13
  • 15
2

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:

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.

Community
  • 1
  • 1
Luiggi Mendoza
  • 85,076
  • 16
  • 154
  • 332
0

Please find the java doc

Returns a synchronized (thread-safe) map backed by the specified map. In order to guarantee serial access, it is critical that all access to the backing map is accomplished through the returned map. It is imperative that the user manually synchronize on the returned map when iterating over any of its collection views:

  Map m = Collections.synchronizedMap(new HashMap());
  ...
  Set s = m.keySet();  // Needn't be in synchronized block
  ...
  synchronized(m) {  // Synchronizing on m, not s!
      Iterator i = s.iterator(); // Must be in synchronized block
       while (i.hasNext())
          foo(i.next());
   }

Failure to follow this advice may result in non-deterministic behavior. The returned map will be serializable if the specified map is serializable.

Parameters: m the map to be "wrapped" in a synchronized map. Returns: a synchronized view of the specified map.

someone
  • 6,577
  • 7
  • 37
  • 60
0

Synchronized has nothing to do with ConcurrentModificationException since it can be take place in a single-threaded environment if you do attempt to remove list item while iterating over the list, using the list's remove method.

Synchronized only guarantees you serial access.

stdout
  • 2,471
  • 2
  • 31
  • 40