【发布时间】:2019-05-13 08:15:53
【问题描述】:
注意:无效问题 - 请参阅@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 - 等待 100 毫秒
- 分配监视器引用以指向新对象
- 再等 1000 毫秒
在主线程中,我们等待 600 毫秒并尝试将监视器重新分配给新对象。
结果 - 主线程被阻塞 - 直到工作线程释放 monitor 对象上的锁定。
这里我有两个问题
- 根据
Concurrency in practice的书——被锁获取进程阻塞的唯一方法——是进入同步阻塞。那么为什么主线程被阻塞直到工作线程释放锁 - 在主线程中我们并没有尝试进入同步块 - 工作线程在 100 毫秒后将新对象分配给
monitor引用,为什么主线程在 600 毫秒后无法获取新重新分配对象的锁定?我的意思是 - 在monitorref 中的 600 毫秒后是新对象 - 所以应该准备好获得锁 这种行为很有趣 - 因为我在 Oracle 官方文档或Concurrency in practice书中找不到任何有关它的信息。
【问题讨论】:
-
>>> 结果 - 主线程被阻塞 - 直到工作线程释放对监视器对象的锁定。如果在主线程从“test”方法返回后由“main”线程启动的“worker”线程,“worker”线程如何在“test”方法中阻塞主线程?看起来您在那里发布的代码与您观察到的主线程被阻塞的代码不同。
标签: java concurrency