我有一个
Foo
类,我认为它应该 not 是线程安全的,但我似乎无法重现这个问题。它具有的一种方法是update
,它根据参数设置当前地图并改变旧地图。另一种方法是read
,它总是从当前地图中获取值。
请查看测试示例。我有两个线程,一个调用
update
,另一个调用read
。我希望 read
有时会从旧版本的 currMap
中读取(因为它不是 volatile
),它被 update
突变,因此返回 -1
,但它没有发生。这是巧合还是意料之中?
private static class Foo {
Map<Integer, Integer> currMap;
Object lock = new Object();
Foo(Map<Integer, Integer> newMap) {
currMap = newMap;
}
void update(Map<Integer, Integer> newMap) {
synchronized (lock) {
Map<Integer, Integer> oldMap = currMap;
currMap = newMap;
oldMap.remove(0);
}
}
int read() {
int val;
synchronized (lock) {
val = currMap.getOrDefault(0, -1);
}
return val;
}
}
@Test
public void testExample() throws InterruptedException {
AtomicInteger readWrong = new AtomicInteger(0);
Map<Integer, Integer> map = new HashMap<>();
map.put(0, 0);
Foo foo = new Foo(new HashMap<>(map));
Thread updater = new Thread(() -> {
while (readWrong.get() == 0) {
foo.update(new HashMap<>(map));
}
});
Thread reader = new Thread(() -> {
while (readWrong.get() == 0) {
if (foo.read() == -1) {
readWrong.incrementAndGet();
}
}
});
updater.start();
reader.start();
updater.join();
reader.join();
assertTrue(readWrong.get() > 0);
}