Collections.synchronizedMap(new LinkedHashMap());没有使Map线程安全

时间:2012-10-31 04:11:54

标签: java multithreading concurrency thread-safety

我正在使用以下构造来创建线程安全Map

Collections.synchronizedMap(new LinkedHashMap());

虽然我收到ConcurrentModificationException错误。

5 个答案:

答案 0 :(得分:7)

没有代码,很难猜出什么是真正的问题,但我的猜测是,你没有使用返回的集合来执行操作。根据{{​​3}}

  

为了保证串行访问,必须通过返回的集合完成对后备集合的所有访问。   当迭代它时,用户必须手动同步返回的集合:

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

不遵循此建议可能会导致非确定性行为。

答案 1 :(得分:5)

这里不要贬低任何其他答案,但下面的代码表明并发修改与实际多线程没什么关系。当你说,迭代一个集合但在迭代时修改它时会引起它....

  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");  
  }

答案 2 :(得分:2)

长话短说,在您的代码中未获得ConcurrentModificationException的解决方案是使用ConcurrentHashMap而不是Collections.synchronizedMap(new LinkedHashMap());。这里的解释:

正如Nambari所说,如果没有实际的代码,问题就更难识别。请注意,此Map仅保护包含的对象。您仍然可以在方法中修改相同的对象实例:

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);
}

同步集合不会保存这些案例的代码。您应该自己同步此方法。

其他信息:如果您正在尝试实施缓存库或Flyweight design pattern,请不要重新发明轮子并使用经过验证且经过测试的框架,例如ehcachejboss cache

答案 3 :(得分:0)

请找到java doc

返回由指定映射支持的同步(线程安全)映射。为了保证串行访问,必须通过返回的映射完成对支持映射的所有访问。 当迭代任何集合视图时,用户必须手动同步返回的地图:

  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());
   }

不遵循此建议可能会导致非确定性行为。 如果指定的映射是可序列化的,则返回的映射将是可序列化的。

参数: 将地图“包装”在同步地图中。 返回: 指定地图的同步视图。

答案 4 :(得分:0)

Synchronized与ConcurrentModificationException无关,因为如果您在迭代列表时尝试删除列表项,则可以在单线程环境中进行,使用列表的remove方法。

同步仅保证您的串行访问。