notifyAll 后 2 线程如何获取锁?
How does 2 thread able to acquire lock after notifyAll?
我正在阅读 Java 中使用 wait/notify/notifyAll 的线程间通信。
我通过了这个答案:
有2个线程和1个主线程。主线程做notifyAll
。它唤醒剩余的 2 个线程,并且两个线程都打印
":syncronized block have finished"
但是我读到如果有 2 个线程在等待锁,notifyAll 会唤醒每个线程,但锁只会被 1 个线程获取。
所以我的问题是 t1 和 t2 线程如何完成它们的执行?
当我从 lock.notifyAll();
更改为 lock.notify();
时,Java 程序永远不会结束。
t1/t2 中的一个线程将处于等待状态。
有人能回答一下吗?我的疑惑我可以再解释一下,以防没看明白。
简单来说就是问题:如果2个线程在等待同一个锁,第3个线程执行notifyAll,只有其中一个获得锁,另一个保持等待状态,那么在上面的例子中,为什么两个线程都能够完成执行呢?
您问题的答案隐藏在 notify() and notifyAll() 方法的文档中。
在您的特定情况下,两个线程同步的锁对象的所有者是主线程。当我们在锁对象上调用 notify() 方法时,如果您看到文档,它会说“only single thread”被唤醒。因此你明白为什么程序会挂起第二个线程永远不会 "notfied" 被唤醒。第一个在进入 "waiting" 状态时释放锁的线程实际上是被唤醒的线程。
如果你看到 "notifyAll()" 的文档,它指出 "Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods." 强调 "all" 意味着你的线程已经获得锁并等待 [=29= 】 被唤醒。
下面是我们将调用从 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
当两个线程调用 wait
时,随后的 notifyAll
将唤醒它们并将一个线程置于 RUNNABLE
状态(在 notifyAll 上同步获取的赢家),另一个进入 BLOCKED
状态(等待获取监视器)。这遵循 wait 和 notifyAll 的语义。
BLOCKED
线程的规则是在当前持有监视器的另一个 RUNNABLE
线程退出后获取监视器。这就是您看到两个输出的原因。
这个 属性 很重要,为什么你应该总是 re-check 让你首先等待的相同条件,这被称为 missed-signal。
我正在阅读 Java 中使用 wait/notify/notifyAll 的线程间通信。
我通过了这个答案:
有2个线程和1个主线程。主线程做notifyAll
。它唤醒剩余的 2 个线程,并且两个线程都打印
":syncronized block have finished"
但是我读到如果有 2 个线程在等待锁,notifyAll 会唤醒每个线程,但锁只会被 1 个线程获取。
所以我的问题是 t1 和 t2 线程如何完成它们的执行?
当我从 lock.notifyAll();
更改为 lock.notify();
时,Java 程序永远不会结束。
t1/t2 中的一个线程将处于等待状态。
有人能回答一下吗?我的疑惑我可以再解释一下,以防没看明白。
简单来说就是问题:如果2个线程在等待同一个锁,第3个线程执行notifyAll,只有其中一个获得锁,另一个保持等待状态,那么在上面的例子中,为什么两个线程都能够完成执行呢?
您问题的答案隐藏在 notify() and notifyAll() 方法的文档中。
在您的特定情况下,两个线程同步的锁对象的所有者是主线程。当我们在锁对象上调用 notify() 方法时,如果您看到文档,它会说“only single thread”被唤醒。因此你明白为什么程序会挂起第二个线程永远不会 "notfied" 被唤醒。第一个在进入 "waiting" 状态时释放锁的线程实际上是被唤醒的线程。
如果你看到 "notifyAll()" 的文档,它指出 "Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the wait methods." 强调 "all" 意味着你的线程已经获得锁并等待 [=29= 】 被唤醒。
下面是我们将调用从 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
当两个线程调用 wait
时,随后的 notifyAll
将唤醒它们并将一个线程置于 RUNNABLE
状态(在 notifyAll 上同步获取的赢家),另一个进入 BLOCKED
状态(等待获取监视器)。这遵循 wait 和 notifyAll 的语义。
BLOCKED
线程的规则是在当前持有监视器的另一个 RUNNABLE
线程退出后获取监视器。这就是您看到两个输出的原因。
这个 属性 很重要,为什么你应该总是 re-check 让你首先等待的相同条件,这被称为 missed-signal。