gpt4 book ai didi

java - 如果将引用重新分配给同步块(synchronized block)内的锁定对象会怎样?

转载 作者:塔克拉玛干 更新时间:2023-11-01 23:00:33 26 4
gpt4 key购买 nike

注意:无效问题 - 请参阅@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 对象。在工作线程中,我们有下一个 Action 序列 -

  • 获取monitor的锁
  • 等待 100 毫秒
  • 分配监视器引用以指向新对象
  • 再等 1000 毫秒

在主线程中,我们等待 600 毫秒并尝试将监视器重新分配给新对象。结果 - 主线程被阻塞 - 直到工作线程释放 monitor 对象上的锁。这里我有两个问题

  1. 根据Concurrency in practice 一书 - 被锁获取过程阻塞的唯一方法 - 是进入同步块(synchronized block)。那么为什么主线程在工作线程释放锁之前一直被阻塞——在主线程中我们并没有试图进入同步块(synchronized block)
  2. 工作线程在 100 毫秒后将新对象分配给 monitor 引用,为什么主线程在 600 毫秒后无法获取新重新分配对象的锁?我的意思是 - 在 monitor 600ms 之后 ref 是新对象 - 所以应该准备好获取锁这种行为很有趣——因为我在官方 Oracle 文档或Concurrency in practice 书中找不到任何关于它的信息。

最佳答案

这段代码

 synchronized (monitor) {

就像

Object m = monitor;
synchronized (m) {

即只读一次,并且在非线程安全的上下文中。

why main thread can not lock on new object - reassigned inside worker thread.

这意味着

  • 一旦获得要锁定的对象,它就不会继续循环读取最新值以查看是否可以锁定另一个对象。
  • 即使引用在读取之前发生更改,它也可能看到旧值,因为读取不是线程安全的。

关于java - 如果将引用重新分配给同步块(synchronized block)内的锁定对象会怎样?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53739401/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com