7

当您在未等待的对象上调用 notifyAll 方法时会发生什么?应该有例外还是正常情况?

4

6 回答 6

8

正如您在此处看到的,在未等待的对象上调用 notifyAll() 没有任何效果。

替代文字

于 2009-05-06T06:54:00.310 回答
7

这是完全正常的。您只能在一台显示器上通知所有等待的人。其他人都不感兴趣。您调用 notifyAll 的对象只是其他人正在等待的监视器。如果没有人在等待,则无需通知任何人

于 2009-05-06T06:32:25.523 回答
3

对象“等待”,而不是等待自己。线程是等待的那个。如果没有人在等待,没有人会醒来,也不会发生什么特别的事情。

于 2009-05-06T08:38:30.060 回答
3

完全正常的情况。

假设您有一个队列,其中一个生产者线程将元素放入其中,一个消费者线程从中删除元素。

现在消费者可能已经清空了队列并且仍然忙于处理,所以没有人在等待队列变为非空。现在生产者将一个新元素添加到队列中。如果消费者正在等待,他必须调用 notifyAll() 来唤醒消费者。添加额外的逻辑来检查是否有人在等待,并且在这种情况下只调用 notifyAll() 会给场景增加相当大的(并且非常容易失败)复杂性 - 每次调用 notifyAll() 会容易得多。

于 2009-05-06T08:51:10.060 回答
1

只有等待的对象会收到通知。Object.wait() 阻塞直到超时或通知 - 所以问题仍然是你认为非等待对象会如何或为什么会得到通知?这没有道理。

于 2009-05-06T06:57:20.207 回答
1

我可能只是分裂头发;-) 在 notifyAll 上将线程从“等待”状态置于“运行”状态可能并不完全正确;至少不是没有通知线程做的第一件事就是重新获取监视器锁。而且由于通知的线程中只有一个可以抢到它,因此其他线程将被阻塞BLOCKED ( Thread.State.Blocked ) 是线程状态。但是阻塞与等待不同,因为被阻塞的线程不需要另一个 notify() 信号来恢复。[好吧,我知道虚假唤醒,但对于某些 JVM 实现来说,情况可能正好相反——错过了通知?]

public class HellBoy {
    public static class MyThread extends Thread {
        static final public Object sharedLock = new Object();

        public void run() {
            synchronized (sharedLock) {
                System.out.println("Gonna wait...");
                try {
                    sharedLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("Woken up but sleeping with the lock");
                try {
                    Thread.sleep(2500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("exiting and unlocking");
            }
        }
    }

    public static void main(String[] args) throws Exception {
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        new MyThread().start();
        Thread.sleep(200);
        synchronized (MyThread.sharedLock) {
            MyThread.sharedLock.notifyAll();
        }
    }
}
于 2012-01-20T16:03:46.417 回答