如果我有下面的代码
synchronized (this)
{
System.out.println("Waiting for return key.");
scanner.nextLine();
System.out.println("Return key pressed.");
notify();
Thread.sleep(5000);
}
在notify
之后,我正在调用睡眠,这意味着,我已经通知了等待线程但没有放弃锁定,现在发生了什么......通知等待线程后会被唤醒但是无法获取锁定,所以从这里开始,这是一个忙碌的等待?因为我们不会再打电话给notify
。
同样的问题与notify
和notifyall
相关,在一个线程唤醒并获得锁定后,是否所有其他线程等待变得忙等待?
答案 0 :(得分:1)
wait()
没有忙碌等待,但一旦通知就会"compete in the usual manner with other threads for the right to synchronize on the object"。
答案 1 :(得分:1)
对notify
的调用唤醒当前正在等待对象条件队列的一个线程,该队列然后尝试重新获取在该时间点仍由调用线程保持的锁。因此,这种情况可以与想要输入当前由另一个线程执行的synchronized
块的线程相媲美。线程没有忙碌等待,它只是被阻止,直到它可以获得锁定。
当调用notify
的线程释放其锁定时,可以取消阻止另一个线程并继续工作。
notifyAll
也是如此,但它会唤醒正在等待对象条件队列的所有线程。由于其中只有一个人可以获得锁定,其他人会一直锁定,直到他们获得锁定 - 一个接一个。这可能因为线程唤醒信号可能是自发的,所以需要始终在条件循环中调用wait
:
synchronized (lockObject) {
// ...
while (!condition) {
lockObject.wait();
}
// object is now in desired state
}
另见:Java Concurrency in Practice,第14.2章
答案 2 :(得分:0)
线程只有在IT拥有对象的监视器时才能在对象上等待。一旦第一个线程通知,第二个线程就会唤醒但不会执行任何操作。这里发生的唯一事情就是“线程将从等待对象的线程列表中删除。它留给操作系统来安排执行。操作系统可能会选择不执行它一段时间。线程没有' t busy-wait。它只是在等待安排的线程集中。
正如@Holger所指出的,任何调用wait()的线程都会释放对象的锁定。一旦通知,它必须“竞争”并重新获取对象的锁定。当持有锁的线程调用notify()时,不会重新获取锁。当该线程退出同步块时会发生这种情况。