Collections.synchronizedMap(new LinkedHashMap()); is not making Map threadsafe
我正在使用以下构造创建一个线程安全
1 |
虽然我得到了
如果没有代码,很难猜出真正的问题是什么,但我猜是,您没有使用返回的集合来执行操作。按照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:
1 2 3 4 5 6 7 | Collection c = Collections.synchronizedCollection(myCollection); ... synchronized(c) { Iterator i = c.iterator(); // Must be in the synchronized block while (i.hasNext()) foo(i.next()); } |
不遵守这一建议可能导致不确定性行为。
这里的代码并没有贬低任何其他答案,但是下面的代码显示并发修改与实际的多线程处理几乎没有关系。它是在您说,对集合进行迭代,但在迭代时对集合进行修改时产生的。
1 2 3 4 5 6 7 8 9 10 |
长话短说,在代码中不使用
- ConcurrentHashMap和Collections.SynchronizedMap(Map)有什么区别?
正如Nambari所说,如果没有实际的代码,这个问题就很难识别。请注意,此
1 2 3 4 5 6 7 8 9 10 11 12 | 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设计模式,不要重新设计轮子,使用一个经过验证和测试的框架,如ehcache或jboss缓存。
Synchronized与ConcurrentModificationException无关,因为如果在使用列表的Remove方法遍历列表时尝试删除列表项,则可以在单线程环境中进行。
同步仅保证串行访问。
请找到Java文档
返回由指定映射支持的同步(线程安全)映射。为了保证串行访问,必须通过返回的映射完成对备份映射的所有访问。在迭代其任何集合视图时,用户必须在返回的映射上手动同步:
1 2 3 4 5 6 7 8 9 | 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要"包装"在同步映射中的映射。返回:指定映射的同步视图。