注意:问题无效-请参阅@Bukhtoyarov Vladimir的评论
假设我们有以下代码:
public class Main {
private Object monitor = new Object();
public static void main(String[] args) throws InterruptedException {
Main main = new Main();
main.test();
new Thread() {
@Override
public void run() {
try {
main.changeMonitor();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}.start();
}
private void test() throws InterruptedException {
synchronized (monitor) {
Thread.sleep(100);
monitor = new Object();
Thread.sleep(1000);
System.out.println("test finished");
}
}
private void changeMonitor() throws InterruptedException {
Thread.sleep(600);
monitor = new Object();
System.out.println("monitor changed");
}
}
在这里,我们有两个线程-主线程和另一个工作线程。另外,我们有monitor
对象。在工作线程中,我们有下一个操作序列-
monitor
的锁定在主线程中,我们等待600毫秒,然后尝试将监视器重新分配给新对象。
结果-主线程被阻塞-直到工作线程释放monitor
对象上的锁为止。
在这里,我有两个问题
Concurrency in practice
一书-锁定获取过程阻止的唯一方法是进入同步块。那么为什么在工作线程释放锁之前阻止主线程-在主线程中,我们不尝试进入同步块monitor
引用,为什么主线程在600毫秒后无法获得对新的重新分配对象的锁定?我的意思是-在monitor
引用中经过600毫秒后,是新对象-因此应该准备好获取锁定
这种行为很有趣-因为我在Oracle官方文档或Concurrency in practice
书中找不到关于它的任何信息。答案 0 :(得分:5)
此代码
synchronized (monitor) {
就像
Object m = monitor;
synchronized (m) {
即只读发生一次,并且在不是线程安全的上下文中。
为什么主线程无法锁定新对象-在工作线程中重新分配。
这是