为什么多次调用 wait() 不会抛出异常?

Why calling wait() more than once is not throwing Exceptions?

我知道在未获得对象所有权的情况下调用 wait() 方法会导致异常。 来自 Java 文档,调用 wait() 线程 * 释放此监视器的所有权并等待另一个线程 * 通知等待此对象监视器的线程唤醒 * 通过调用 {@code notify} 方法或 * {@code notifyAll} 方法。 因此,一旦在对象上调用 wait(),该特定线程就会失去对该对象的所有权,直到其他线程通知它。

为什么在没有通知的情况下调用wait()两次,没有抛出错误? 为了确保,..我只是 运行 生产者,所以没有其他线程在那里通知它并且 wait() 方法被无限次调用。 然而,尽管在第一次 wait() 调用后失去了所有权,但随后的等待调用应该抛出 exceptions.isn'?但为什么它工作正常?

class Producer extends Thread {

    private Queue<Integer> queue;
    private int maxSize;

    public Producer(Queue<Integer> queue, int maxSize, String name) {
        super(name);
        this.queue = queue;
        this.maxSize = maxSize;
    }

    public void run() {
        while (true) {
            synchronized (queue) {
                try {
                    queue.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }

        }

    }
}

如果您只 运行 那个线程,它会在等待(尝试添加调试输出)之后阻塞。

wait() 阻塞直到收到通知,并在返回前重新获取锁。即,当 wait() returns 在您的示例中,您再次锁定 queue.

编辑:每次更新问题

因此,"calling wait() twice without notifying" 是不可能的,因为第一次调用 wait() 将阻塞线程,直到收到通知。不能在循环中无限次调用,要么阻塞,要么抛异常。

加法:

顺便说一下,"naked" 等待通常是有风险的,因为无法保证哪个等待线程被唤醒(例如,生产者或消费者)。 一个常见的习语(如 Java "built-in monitors" -- synchronized 块 -- 没有条件变量)类似于

while(! condition)
    wait();

在这种情况下,对于消费者来说,可能类似于

while(queue.isEmpty())
    wait();