我正在编写一个代码,该代码在其构造函数中接受一个 Map,并将其分配给一个实例变量。任何使用此实例变量map
的方法都会被同步。
class Foo {
Map<Int, Int> map;
Foo ( Map<Int, Int> map ) {
this.map = map;
}
synchornized void put(int x, int y) {
map.put(x, y);
}
}
但是 - 客户端创建了 Foo 的多个实例,并将相同的映射实例传递给每个实例。
Map<Int, Int> map = new HashMap<Int, Int>();
new Foo(map);
new Foo(map);
在不同实例上使用map
时如何同步?
让问题更广泛,如何全局同步实例?
最佳答案
您应该在 map
上同步,而不是在 foo
实例本身上同步。
即
void put(int x, int y) {
synchronized (map) {
map.put(x, y);
}
}
<小时/>
编辑:
这里的关键点是,您需要了解同步的概念,并识别共享且需要同步的“资源”。在您的情况下,共享资源是 Map,而不是 Foo 实例本身。并发访问 Map 可能会导致问题,因此您应该同步的是共享资源 - Map 本身。
还有一些其他答案建议使用 ConcurrentHashMap。 ConcurrentHashMap 在某些情况下可以提供帮助,但它不会涵盖同步块(synchronized block)(或使用某种其他类型的锁定机制)的可能性
ConcurrentMap解决了向Map提供一些“复杂”操作的问题,这些操作过去需要多次访问,因此需要对Map进行显式锁定。 ConcurrentHashMap 更进一步,实现了线程安全的无锁读取等。
但是,这并不一定能解决问题。
假设我需要在 Map 上执行的不是提供的操作: 例如
synchronized(map) {
if (map.contains("key1")) {
map.put("key3", val1);
} else if (map.contains("key2")) {
map.put("key3", val);
}
}
,那么我将需要显式锁定(在这种情况下,ConcurrentHashMap 可能更糟,因为它不允许我执行显式同步)
关于java - 如何同步传递到多个地方的实例?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/22651763/