当有多个生产者消费者时,如果多个线程都处于wait()
状态时,如果持有锁的线程释放锁,抢到锁的线程不会再次判断,举例如下:
class Test {
private int num = 0;
public synchronized void sub() throws InterruptedException {
if (num != 1) {
this.wait();
}
num--;
System.out.println(Thread.currentThread().getName() + " num=" + num);
this.notifyAll();
}
public synchronized void add() throws InterruptedException {
if (num != 0) {
this.wait();
}
num++;
System.out.println(Thread.currentThread().getName() + " num=" + num);
this.notifyAll();
}
}
如果使用if
当有多个线程执行add()
和sub()
时,会出现虚假唤醒问题
比如:
此刻num = 1
,a线程
抢到了add
的锁,发现num!=0
,然后停在代码的第15行,释放锁,然后b线程
抢到了add
锁,发现num!=0
,同样停在了代码第15行,释放锁,然后c线程
抢到了sub
的锁,num
变成了0,唤醒所有线程,然后a线程
抢到了add
的锁,执行第16行,然后执行第17行,直至释放锁,释放完之后,b线程
抢到了add
的锁,然后并没有判断而是直接执行第16,17行,就无法完成生产一个消费一个的功能。
如果把if
换成while
就可以解决这个问题,a线程
抢到add
锁之后,执行完16行之后会继续判断,发现num是0
之后才执行第17行,b线程抢到锁之后,执行完16行也会判断,此时num为1
,所以b线程并不会执行加一操作。