在notify()之后做很多工作会导致wait()变得忙碌等待吗?

时间:2014-05-13 05:21:26

标签: java multithreading synchronized monitor busy-waiting

如果我有下面的代码

synchronized (this)
{
    System.out.println("Waiting for return key.");
    scanner.nextLine();
    System.out.println("Return key pressed.");
    notify();
    Thread.sleep(5000);
}

notify之后,我正在调用睡眠,这意味着,我已经通知了等待线程但没有放弃锁定,现在发生了什么......通知等待线程后会被唤醒但是无法获取锁定,所以从这里开始,这是一个忙碌的等待?因为我们不会再打电话给notify

同样的问题与notifynotifyall相关,在一个线程唤醒并获得锁定后,是否所有其他线程等待变得忙等待?

3 个答案:

答案 0 :(得分:1)

答案 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()时,不会重新获取锁。当该线程退出同步块时会发生这种情况。