当有多个生产者消费者时,如果多个线程都处于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线程并不会执行加一操作。
