【问题标题】:Lock released after calling wait() method?调用 wait() 方法后释放锁?
【发布时间】:2018-05-11 07:07:44
【问题描述】:

我正在阅读有关 Java 中的等待和通知。

我会用一个小例子来解释:

@Override
    public void run() {
        synchronized (msg) {
            try{
                msg.wait();
            }catch(InterruptedException e){
                e.printStackTrace();
            }
            System.out.println(name+" processed: "+msg.getMsg());
        }
    }

这里说当我们做synchronized (msg)时。当前线程 T1 将锁定 msg 对象。

所以锁可以通过两种方式释放:

  1. 同步块完成后
  2. 当 wait() 被 T1 调用时??

如果另一个线程调用 notify() 并唤醒线程 T1,T1 将再次获得锁定msg 对象的访问权限?

【问题讨论】:

  • T1 没有必要在收到通知后立即开始执行,它与等待访问对象锁的其他线程竞争。

标签: java multithreading thread-safety


【解决方案1】:

是的,T1 会在wait 时释放锁,收到通知后必须重新获取锁。详情见java language specification。

并且,wait 方法 should 在 while 循环中被调用。

 synchronized (obj) {
     while (<condition does not hold>)
         obj.wait();
     ... // Perform action appropriate to condition
 }

【讨论】:

    【解决方案2】:

    Lock在调用wait()后被释放。

    如果另一个线程调用 notify() 并唤醒线程 T1,T1 将再次获得访问 msg 对象的锁定权限?

    它不会自动获得锁定权限。它必须与其他线程竞争。

    在notify()(来自 javadocs):

    唤醒在此对象的监视器上等待的单个线程。如果有任何线程正在等待该对象,则选择其中一个被唤醒。线程通过调用其中一个等待方法在对象的监视器上等待。

    在当前线程放弃对该对象的锁定之前,被唤醒的线程将无法继续。被唤醒的线程将以通常的方式与可能正在积极竞争以在该对象上同步的任何其他线程竞争;例如,被唤醒的线程在成为下一个锁定该对象的线程方面没有任何可靠的特权或劣势。

    【讨论】:

      猜你喜欢
      • 2018-11-13
      • 2018-03-01
      • 2021-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-05
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多