Java多线程为什么使用while循环来调用wait方法?《java并发编程实战》一书第14章列出了详细的原因(多看书还是会有收获滴),在此总结下来。示例代码:
//示例代码,从队列中获取元素
public synchronized void put(V v) throws InterruptedExcetpion{
//不能使用if(isFull)
while(isFull()){
wait();
}
doPut(v)
notivyALl();
}
详细原因博主梳理如下: 1、当线程A执行到wait方法会释放锁,同时线程A被阻塞。 2、当线程A被唤醒的时候,wait()仍然需要重新获取锁。 3、在线程A被唤醒到wait()重新获取锁的这段时间里,线程B可能已经获取到了锁, 并且修改了相关状态。此时线程A获取到锁之后,isFull方法又变成了true,那么在执行doPut()就会出错。确切的说是因为其他线程notifyAll的时候,所有因为wait被阻塞的线程都去尝试获取锁,只有一个线程获取到了锁并没有获取到锁,导致isFull方法可能又变成真。 4、wait方法被唤醒的时候,可能isFull不为true,因为你并不知道线程B什么时候调用了notify或者notifyAll.
基于以上原因,我们需要把wait方法while语句里面执行。事实上主要原因就是前两个即:wait需要需要释放锁和被唤起时需要重新获取锁。