对wait()方法进行判断为什么用while而不是if?

wait¬ify 实践

等待方(消费者)和通知方(生产者)

在单个消费者和单个生产者的模型下,使用while或者if都不会出错。
但是在有多个消费者时,使用if进行判断就会出错

等待方:
synchronized(obj){
while(条件不满足){
	 obj.wait();
}
消费;
}

通知方:
synchonized(obj){
	改变条件;
	obj.notifyAll();
}

1)条件谓词:
将与条件队列相关联的条件谓词以及在这些条件谓词上等待的操作都写入文档。
在条件等待中存在一种重要的三元关系,包括加锁、wait 方法和一个条件谓词。在条件谓
词中包含多个状态变量,而状态变量由一个锁来保护,因此在测试条件谓词之前必须先持有
这个锁。锁对象和条件队列对象(即调用 wait 和 notify 等方法所在的对象)必须是同一个
对象。
当线程从 wait 方法中被唤醒时,它在重新请求锁时不具有任何特殊的优先性,而要去其他
尝试进入同步代码块的线程一起正常地在锁上进行竞争。
每一次 wait 调用都会隐式地与特定的条件谓词关联起来。当调用某个特定条件谓词的 wait
时,调用者必须已经持有与条件队列相关的锁,并且这个锁必须保护着构成条件谓词的状态
变量。

2)过早唤醒:
虽然在锁、条件谓词和条件队列之间的三元关系并不复杂,但 wait 方法的返回并不一定意
味着线程正在等待的条件谓词已经变成真了。
当执行控制重新进入调用 wait 的代码时,它已经重新获取了与条件队列相关联的锁。现在
条件谓词是不是已经变为真了?或许。在发出通知的线程调用 notifyAll 时,条件谓词可能已
经变成真,但在重新获取锁时将再次变成假。在线程被唤醒到 wait 重新获取锁的这段时间
里,可能有其他线程已经获取了这个锁,并修改了对象的状态。或者,条件谓词从调用 wait
起根本就没有变成真。你并不知道另一个线程为什么调用 notify 或 notifyAll,也许是因为与
同一条件队列相关的另一个条件谓词变成了真。一个条件队列与多个条件谓词相关是一种很
常见的情况。
基于所有这些原因,每当线程从 wait 中唤醒时,都必须再次测试条件谓词。
所以每当线程要调用wait()方法时,需要使用while()进行条件判断而不是if();

你可能感兴趣的:(对wait()方法进行判断为什么用while而不是if?)