我知道调用wait()
方法而不获取对象的所有权会导致异常。
和来自Java doc,调用wait()
线程
*释放此监视器的所有权并等待另一个线程
*通知在此对象的监视器上等待的线程被唤醒
*通过调用他{@code notify}
方法或者
* {@code notifyAll}
方法。
所以一旦在对象上调用wait()
,该特定线程就会失去对该对象的所有权,直到其他一些线程通知它为止。
为什么在没有通知的情况下两次调用wait()
,而不是抛出错误?
为了确保,..我只是运行生产者,所以没有其他线程我在那里通知它和wait()
方法被称为无限次。
然而,尽管在第一次wait()
调用后失去了对它的所有权,随后的等待调用应该抛出异常。不是吗?但为什么它工作正常?
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();
}
}
}
}
}
答案 0 :(得分:4)
如果你只运行那个线程,它会在等待之后阻塞(尝试添加一个调试输出)。
wait()
阻止直到收到通知,并在返回之前重新获取锁。即,在您的示例中wait()
返回时,您再次锁定了queue
。
修改:每次更新问题
因此,&#34;两次调用wait()
而不通知&#34;是不可能的,因为对wait()
的第一次调用将阻止该线程,直到通知为止。它不能在循环中被称为无限次,它会阻塞或抛出异常。
<强>增加:强>
顺便说一句,有一个&#34;裸体&#34;等待通常是有风险的,因为不能保证唤醒哪些等待线程(例如,生产者或消费者)。 一个常见的习语(如Java&#34;内置监视器&#34; -synchronized
块 - 没有条件变量)就像是
while(! condition)
wait();
在这种情况下,对于消费者来说,或许类似
while(queue.isEmpty())
wait();