【问题标题】:Why `synchronized (lock)` was entered twice by different threads?为什么不同的线程两次输入了“同步(锁定)”?
【发布时间】:2018-11-14 13:24:44
【问题描述】:

在这个简单的例子中,我有两个 synchronized (theLock) 被不同的线程访问

public class Main {

    public static void main(String[] args) throws InterruptedException {
        System.out.println("start");

        final Object theLock = new Object();

        synchronized (theLock) {
            System.out.println("main thread id : " + Thread.currentThread().getId());

            new Thread(() -> {
                System.out.println("new thread id : " + Thread.currentThread().getId() + ". Inside thread");

                // before entering this section new thread should be blocked as `theLock` is already acquired
                synchronized (theLock) {
                    System.out.println("inside synchronized");
                    theLock.notify();
                }
            }).start();

            theLock.wait();
        }

        System.out.println("end");
    }
}

为什么新创建的线程可以访问synchronized (theLock)里面的部分?据我了解,theLock 已经被主线程获取,新的应该永远阻塞。相反,我看到它也进入了synchronized

这是一个输出

start
main thread id : 1 
new thread id : 13. Inside thread
inside synchronized
end

【问题讨论】:

  • 原始线程调用theLock.wait(),这意味着它释放锁并等待通知。然后第二个线程获取锁,调用notify,释放锁。然后第一个线程被唤醒,获得锁,然后继续。

标签: java multithreading synchronized synchronized-block


【解决方案1】:

wait() 的调用会释放锁。 Per wait() Javadoc(加粗我的):

使当前线程等待直到另一个线程调用 此对象的notify() 方法或notifyAll() 方法。在 换句话说,这个方法的行为就像它只是简单地执行 致电wait(0)

当前线程必须拥有该对象的监视器。 线程 释放此监视器的所有权 并等到另一个线程 通知在此对象的监视器上等待的线程唤醒 通过调用notify 方法或notifyAll 方法。这 然后线程等待直到它可以重新获得监视器的所有权,然后 恢复执行。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多