当有多个生产者消费者时,如果多个线程都处于wait()状态时,如果持有锁的线程释放锁,抢到锁的线程不会再次判断,举例如下:

    1. class Test {
    2. private int num = 0;
    3. public synchronized void sub() throws InterruptedException {
    4. if (num != 1) {
    5. this.wait();
    6. }
    7. num--;
    8. System.out.println(Thread.currentThread().getName() + " num=" + num);
    9. this.notifyAll();
    10. }
    11. public synchronized void add() throws InterruptedException {
    12. if (num != 0) {
    13. this.wait();
    14. }
    15. num++;
    16. System.out.println(Thread.currentThread().getName() + " num=" + num);
    17. this.notifyAll();
    18. }
    19. }

    如果使用if当有多个线程执行add()sub()时,会出现虚假唤醒问题
    比如:
    此刻num = 1a线程抢到了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线程并不会执行加一操作。