注意:无效的问题 - 请参阅@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");
}
}
Run Code Online (Sandbox Code Playgroud)
这里我们有两个线程 - 主线程和另一个工作线程.我们也有monitor对象.在工作线程内部,我们有下一步的动作 -
monitor在主线程中,我们等待600毫秒并尝试将监视器重新分配给新对象.结果 - 主线程被阻塞 - 直到工作线程释放锁定monitor对象.我有两个问题
Concurrency in practice本书 - 锁定水分过程阻止的唯一方法 - 是进入同步块.那么为什么主线程被阻塞直到工作线程释放锁定 - 在主线程中我们不会尝试进入同步块monitor在100ms后分配新对象引用,为什么主线程在600ms后无法获取新重新分配对象的锁定?我的意思是 - 在refms中600ms之后monitor是新对象 - 所以锁定应该准备好了.行为很有意思 - 因为我在官方的Oracle文档或Concurrency in practice书中找不到任何关于它的信息.这段代码
synchronized (monitor) {
Run Code Online (Sandbox Code Playgroud)
就好像
Object m = monitor;
synchronized (m) {
Run Code Online (Sandbox Code Playgroud)
即只读一次,并且在非线程安全的上下文中.
为什么主线程无法锁定新对象 - 在工作线程内部重新分配.
这意味着