【问题标题】:How does 2 thread able to acquire lock after notifyAll?notifyAll 后 2 个线程如何获取锁?
【发布时间】:2019-11-18 20:21:15
【问题描述】:

我正在阅读有关 Java 中使用 wait/notify/notifyAll 的线程间通信。

我通过了这个答案:https://stackoverflow.com/a/36276832

有 2 个线程和 1 个主线程。主线程做notifyAll。它唤醒剩余的 2 个线程,并且两个线程都打印

":syncronized block have finished"

但是我读到如果有 2 个线程在等待一个锁,notifyAll 会唤醒每个线程,但锁只会被 1 个线程获取。

所以我的问题是 t1 和 t2 线程是如何完成它们的执行的?

当我从lock.notifyAll(); 更改为lock.notify(); 时,Java 程序永远不会结束。

t1/t2 中的一个线程将处于等待状态。

有人可以回答吗?如果没有理解清楚,我可以进一步解释我的疑问。

简单的问题:如果2个线程在等待同一个锁,而第3个线程做notifyAll,只有一个得到锁,另一个保持等待状态,所以在上面的情况下,怎么两个线程都能完成执行?

【问题讨论】:

  • 一旦线程一释放锁,线程二得到它。
  • 但是线程1没有调用notify,怎么唤醒的?

标签: java multithreading wait synchronized


【解决方案1】:

您的问题的答案隐藏在 notify()notifyAll() 方法的文档中。

在您的特定情况下,两个线程正在同步的锁对象的所有者是主线程。当我们在锁对象上调用 notify() 方法时,如果你看到文档说“only single thread”被唤醒。因此,您会看到为什么程序会挂起第二个线程永远不会“通知”被唤醒。第一个释放锁进入“等待”状态的线程实际上是被唤醒的线程。

如果您看到“notifyAll()”的文档,它指出“唤醒 所有 正在等待此对象监视器的线程。线程通过调用其中一个等待方法在对象的监视器上等待。”强调“全部”意味着您的已获得锁并等待“通知”的线程都被唤醒。

下面是当我们将调用从 notifyAll() 更改为 notify() 时的结果,在这种情况下会通知第一个执行等待的线程。

Time: Tue Jul 09 12:42:37 CDT 2019;Thread-1:thread goes into waiting state and releases the lock
Time: Tue Jul 09 12:42:37 CDT 2019;Thread-0:only one thread can be in synchronized block
Time: Tue Jul 09 12:42:42 CDT 2019;Thread-0:thread goes into waiting state and releases the lock
Time: Tue Jul 09 12:42:47 CDT 2019;Notifying all
Time: Tue Jul 09 12:42:47 CDT 2019;Thread-1:thread is awake and have reacquired the lock
Time: Tue Jul 09 12:42:47 CDT 2019;Thread-1:syncronized block have finished

【讨论】:

    【解决方案2】:

    当两个线程调用wait 时,随后的notifyAll 将唤醒它们,并将其中一个线程置于RUNNABLE 状态(在notifyAll 上同步获取的获胜者),另一个置于BLOCKED 状态(等待获取监视器)。这遵循 wait 和 notifyAll 的语义。

    BLOCKED 线程的规则是在当前持有监视器的另一个 RUNNABLE 线程退出后获取监视器。这就是您看到两个输出的原因。

    这个属性很重要,为什么您应该始终重新检查让您首先进入等待的相同条件,这称为missed-signal

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-12-02
      • 2022-08-20
      • 2021-03-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-13
      相关资源
      最近更新 更多