Java 如果将引用重新分配给同步块内的锁定对象,将会发生什么?
注意:无效问题-见@Bukhtoyarov Vladimir的评论 假设我们有以下代码:Java 如果将引用重新分配给同步块内的锁定对象,将会发生什么?,java,concurrency,Java,Concurrency,注意:无效问题-见@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 Thr
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");
}
}
这里我们有两个线程-主线程和另一个工作线程。我们还有监视器
对象。在工作线程中,我们有下一个操作序列-
- 在
监视器上获取锁
- 等待100毫秒
- 将监控器引用指定给新对象
- 再等1000毫秒
监视器
对象上的锁。
这里我有两个问题
monitor
reference,为什么主线程在600ms后无法获得重新分配的新对象的锁?我的意思是-在监视器中600毫秒后
ref是新对象-所以应该准备好获得锁
这种行为很有趣——因为我在Oracle官方文档或《实践中的并发性》一书中找不到任何关于它的信息 synchronized (monitor) {
就像
Object m = monitor;
synchronized (m) {
i、 e.只读只发生一次,并且在非线程安全的上下文中
为什么主线程不能锁定新对象-在工作线程内重新分配
这意味着
- 一旦获得了要锁定的对象,它就不会一直读取循环中的最新值以查看是否可以锁定另一个对象
- 即使在读取之前更改了引用,它也会看到一个旧值,因为读取不是线程安全的
对象m
-从未使用引用?仍然不清楚为什么main
线程被锁定-我们没有在main
线程中进入同步
块。其次,为什么main
线程不能锁定新对象-在工作线程内部重新分配。请您在官方文件或至少其他来源中提供参考-我找不到?@OleksandrPapchenko当您引用变量时,它只读取一次,不会重复读取。注意:您没有锁定字段,而是锁定该字段引用的对象。>>>结果-主线程被阻塞-直到工作线程释放监视器对象上的锁。如果在主线程从“测试”方法返回后,由“主”线程启动的“工作”线程在“测试”方法内如何被“工作”线程阻塞?看起来您在那里发布了与您观察到的主线程被阻塞的代码不同的代码。