【发布时间】:2019-05-23 22:01:20
【问题描述】:
相关Java will synchronized block if changed?
public class TestConcurrentTwo {
public static void main(String[] args) {
class lock {
public Object lockObj = new Object();
int protectedValue = 0;
}
lock a = new lock();
Thread t = new Thread(() -> {
try {
synchronized (a.lockObj) {
System.out.println("from first block start");
System.out.println(a.protectedValue);
a.lockObj = new Object();
Thread.sleep(1000);
System.out.println(a.protectedValue);
System.out.println("from first block done");
}
} catch (InterruptedException x) {}
});
t.start();
try {
Thread.sleep(100);
} catch (InterruptedException x) {}
synchronized (a.lockObj) {
System.out.println("from second block start");
a.protectedValue++;
System.out.println("from second block done");
}
System.out.println(a.protectedValue);
}
}
输出:
from first block start
0
from second block start
from second block done
1
1
from first block done
在相关答案中,它们都持有原始引用,因此第二个块应该被阻止,直到第一个块完成。
但是,一旦a.lockObj 从第一个块更改,第二个块确实进行了。为什么?
【问题讨论】:
-
你的两个线程使用不同的锁。第一个线程持有a,lockObj 引用的第一个Object 实例,第二个线程持有a.lockObj 引用的第二个Object 实例。这很容易避免:不要重新分配正在同步的对象。
-
其他答案中的一些措辞使 IMO 感到困惑,特别是“参考”一词的使用,让我们将成员
a.lockObj称为 参考;a.lockObj引用的Object是引用的对象。同步取决于被引用的对象,而不是引用。有两个不同的引用对象用于同步;结果痛苦。
标签: java multithreading