-1

如果我有下面的代码

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

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

同样的问题是,在一个线程被唤醒notifynotifyall获得锁之后,所有其他等待的线程是否都变成了忙等待?

4

3 回答 3

2

wait()不忙等待,但一旦通知,它确实“以通常的方式与其他线程竞争对象同步的权利” 。

于 2014-05-13T05:36:14.947 回答
1

调用notify唤醒一个线程,该线程当前在对象的条件队列上等待,然后尝试重新获取在该时间点仍由调用线程持有的锁。所以这种情况就好比一个线程想要进入一个synchronized当前正在被另一个线程执行的块。线程没有做忙等待,它只是被阻塞,直到它可以获取锁。

当调用的线程notify释放它的锁时,另一个线程可以被解除阻塞并继续工作。

也是如此notifyAll,但它会唤醒所有等待对象条件队列的线程。由于其中只有一个可以获取锁,因此其他人在获得锁之前一直处于阻塞状态 - 一个接一个。这是因为线程唤醒信号可能会自发发生,因此需要始终wait在条件循环内调用:

synchronized (lockObject) {
    // ...
    while (!condition) {
        lockObject.wait();
    }
    // object is now in desired state
}

另请参阅:Java 并发实践,第 14.2 章

于 2014-05-13T07:22:42.093 回答
0

只有当它拥有对象的监视器时,线程才能等待对象。一旦第一个线程通知,第二个线程就会唤醒但不做任何事情。这里唯一发生的是“线程将从等待对象的线程列表中删除。它留给操作系统来安排它的执行。操作系统可能会选择不执行它一段时间。线程没有” t busy-wait. 它只是在等待调度的线程集中。

正如@Holger 指出的那样,任何调用 wait() 的线程都会释放对象上的锁。一旦收到通知,它就必须“竞争”并重新获得对象上的锁。当持有锁的线程调用 notify() 时,不会重新获取锁。当该线程退出其同步块时会发生这种情况。

于 2014-05-13T07:09:58.373 回答