【发布时间】:2018-10-09 08:07:49
【问题描述】:
我有两个线程 thread_1 和 thread_2 在同一个对象 unsafeObj 上调用不同的方法。
-
thread_1 调用
unsafeObj.incrementVAR_v1()10 次 -
thread_2 调用
unsafeObj.incrementVAR_v2()10 次
这两个实例方法都有一个 synchronized-block 和不同的锁(LOCK_1 和 LOCK_2)访问同一个实例字段 VAR。
public void icrementVAR_v1() {
synchronized(LOCK_1) {
++VAR;
print("Thread 1: " + VAR)
}
}
public void incrementVAR_v2() {
synchronized(LOCK_2) {
++VAR;
print("Thread 2: " + VAR);
}
}
????鉴于这两个synchronized 块使用不同的锁,我预计VAR 会被同时访问,从而导致更新丢失(VAR 小于 20)。然而,这不是我观察到的。有人可以向我解释为什么不是这样吗?
示例输出:
Thread 2: 2
Thread 1: 1
Thread 2: 3
Thread 1: 4
Thread 2: 5
Thread 1: 6
Thread 2: 7
Thread 1: 8
Thread 2: 9
Thread 1: 10
Thread 2: 11
Thread 1: 12
Thread 2: 13
Thread 1: 14
Thread 2: 15
Thread 1: 16
Thread 2: 17
Thread 1: 18
Thread 2: 19
Thread 1: 20
【问题讨论】:
-
另外我希望
unsafeObj.incrementVAR_v1()会在新线程开始之前完成,尝试引入大量的计数和一些睡眠时间 -
你能尝试在这两种方法中使用LOCK_1,看看它是如何工作的吗?可能我们误解了同步块的功能,如果您使用不同的锁,它们会同步执行。
-
我有时会得到正确的结果,每种方法运行 10000 次。所以不要指望它每次都能工作。或者期望它会产生“错误”的结果。两者都可能发生,但数量如此之少,可能不会。
-
@NullReference 是的,当您写入 System.out 时,它也会获得对 OutputStream 实例的锁定
-
我猜这是因为
++VAR只编译成两行汇编,除非处理器超级忙,否则不太可能分开?
标签: java multithreading race-condition synchronized