Java 如果将引用重新分配给同步块内的锁定对象,将会发生什么?

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

注意:无效问题-见@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");
    }
}
这里我们有两个线程-主线程和另一个工作线程。我们还有
监视器
对象。在工作线程中,我们有下一个操作序列-

  • 监视器上获取锁
  • 等待100毫秒
  • 将监控器引用指定给新对象
  • 再等1000毫秒
在主线程中,我们正在等待600毫秒,并尝试将监视器重新分配给一个新对象。 结果-主线程被阻塞-直到工作线程释放
监视器
对象上的锁。 这里我有两个问题

  • 根据《实践中的并发》(Concurrency in practice)一书,锁获取进程阻止的唯一方法是进入同步块。那个么为什么主线程在工作线程释放锁定主线程之前被阻塞呢?我们并没有试图进入同步块
  • 工作线程在100ms后将新对象分配给
    monitor
    reference,为什么主线程在600ms后无法获得重新分配的新对象的锁?我的意思是-在
    监视器中600毫秒后
    ref是新对象-所以应该准备好获得锁 这种行为很有趣——因为我在Oracle官方文档或《实践中的并发性》一书中找不到任何关于它的信息
  • 此代码

     synchronized (monitor) {
    
    就像

    Object m = monitor;
    synchronized (m) {
    
    i、 e.只读只发生一次,并且在非线程安全的上下文中

    为什么主线程不能锁定新对象-在工作线程内重新分配

    这意味着

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

    我无法理解您的答案-为什么
    对象m
    -从未使用引用?仍然不清楚为什么
    main
    线程被锁定-我们没有在
    main
    线程中进入
    同步
    块。其次,为什么
    main
    线程不能锁定新对象-在工作线程内部重新分配。请您在官方文件或至少其他来源中提供参考-我找不到?@OleksandrPapchenko当您引用变量时,它只读取一次,不会重复读取。注意:您没有锁定字段,而是锁定该字段引用的对象。>>>结果-主线程被阻塞-直到工作线程释放监视器对象上的锁。如果在主线程从“测试”方法返回后,由“主”线程启动的“工作”线程在“测试”方法内如何被“工作”线程阻塞?看起来您在那里发布了与您观察到的主线程被阻塞的代码不同的代码。