Map<String,Integer> m1 = new ConcurrentHashMap<>();
Map<String,Integer> m2 = new ConcurrentHashMap<>();
public void update(int i) {
m1.put("key", i);
m2.put("key", i);
}
在上面的虚拟代码中,对m1&amp;的更新m2不是原子的。如果我尝试同步这个块,findBugs会抱怨“在util.concurrent实例上执行同步”
除了不使用并发集合并明确地执行所有同步之外,是否有建议的方法来执行此操作。
另外,我也不知道在显式同步中包装并发集合的确切含义。
答案 0 :(得分:2)
如果意图是对于一个键,两个映射总是检索相同的值,则使用两个不同的并发映射的设计是有缺陷的。即使您同步写入,读取线程仍然可以在写入时访问两个映射。这可能是FindBugs规则试图捕获的内容。
有两种方法可以解决这个问题,要么使用显式同步(即使用同步读取和写入的两个常规映射),要么使用只有一个并发映射和放入一个值对象hold 两个整个。
答案 1 :(得分:1)
ConcurrentMap
不是synchronized map。后者确实会自行同步,因此Map
上的同步会对其他Map
操作产生影响。
相比之下,ConcurrentMap
旨在允许不同键的并发更新,并且不会自身同步,因此如果其他代码在Map实例上同步,则它不起作用。使用不同的互斥锁是没有用的;只要其他线程在不使用此互斥锁的情况下在相同的映射上执行操作,它们就不会尊重您预期的原子性。另一方面,如果所有线程都使用互斥锁来访问地图,则不再需要ConcurrentMap
。
但是作为Jarrod Roberson noted,这可能是X-Y Problem,因为原子地更新两个地图而没有两个地图的原子读取,没有线程会注意到更新是否原子地发生。问题是你真正想要实现的目标,或者你真的不需要原子性,或者你不应该使用ConcurrentMap
。