我正在使用以下构造来创建 threadsafe Map
。
Collections.synchronizedMap(new LinkedHashMap());
虽然我遇到了ConcurrentModificationException
错误。
我正在使用以下构造来创建 threadsafe Map
。
Collections.synchronizedMap(new LinkedHashMap());
虽然我遇到了ConcurrentModificationException
错误。
没有代码很难猜出真正的问题是什么,但我的猜测是,您没有使用返回的集合来执行操作。根据javadoc
为了保证串行访问,对后备集合的所有访问都是通过返回的集合完成的,这一点至关重要。当迭代它时,用户必须手动同步返回的集合:
Collection c = Collections.synchronizedCollection(myCollection);
...
synchronized(c) {
Iterator i = c.iterator(); // Must be in the synchronized block
while (i.hasNext())
foo(i.next());
}
不遵循此建议可能会导致不确定的行为。
不要贬低这里的任何其他答案,但下面的代码表明并发修改与实际的多线程几乎没有关系。当您说迭代集合但在迭代时对其进行修改时会引起这种情况......
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");
}
长话短说,ConcurrentModificationException
在您的代码中不包含 a 的解决方案是使用 aConcurrentHashMap
而不是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);
}
同步集合不会为这些情况保存您的代码。你应该自己同步这个方法。
附加信息:如果您正在尝试实现缓存库或享元设计模式,请不要重新发明轮子并使用经过验证和测试的框架,例如ehcache或jboss cache。
请找到java文档
返回由指定映射支持的同步(线程安全)映射。为了保证串行访问,对支持映射的所有访问都是通过返回的映射完成的,这一点至关重要。当迭代其任何集合视图时,用户必须在返回的地图上手动同步:
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());
}
不遵循此建议可能会导致不确定的行为。如果指定的映射是可序列化的,则返回的映射将是可序列化的。
参数: m 要“包装”在同步地图中的地图。返回: 指定地图的同步视图。
Synchronized 与 ConcurrentModificationException 无关,因为如果您在使用列表的 remove 方法迭代列表时尝试删除列表项,它可以在单线程环境中发生。
同步仅保证您的串行访问。