我正在使用以下构造来创建线程安全Map
。
Collections.synchronizedMap(new LinkedHashMap());
虽然我收到ConcurrentModificationException
错误。
答案 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,请不要重新发明轮子并使用经过验证且经过测试的框架,例如ehcache或jboss 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方法。
同步仅保证您的串行访问。