【Java多线程】多线程虚假唤醒

public class CustomerDemo {
    public static void main(String[] args) {
        /**
         * 要求一个线程增加,一个线程减少
         */
        Number number= new Number();
        new Thread(() -> {
            for (int i = 0; i < 10 ;i ++) {
                try {
                    number.decrease();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "A").start();

        new Thread(() -> {
            for (int i = 0; i < 10 ;i ++) {
                try {
                    number.increase();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "B").start();

        new Thread(() -> {
            for (int i = 0; i < 10 ;i ++) {
                try {
                    number.decrease();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "C").start();


        new Thread(() -> {
            for (int i = 0; i < 10 ;i ++) {
                try {
                    number.increase();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }, "D").start();
    }
}


/**
 * 线程之间的通信
 */
class Number {

    private int num = 0;

    public synchronized void decrease() throws InterruptedException {
        if (num == 0) {
            this.wait();
        }
        num --;
        System.out.println(Thread.currentThread().getName() + " ... " + num);
        this.notifyAll();
    }

    public synchronized void increase() throws InterruptedException {
        if (num != 0) {
            this.wait();
        }
        num ++;
        System.out.println(Thread.currentThread().getName() + " ... " + num);
        this.notifyAll();
    }

}

上面程序最理想的状态是0 ,1,0,1间隔执行,但是多执行几次就有可能会出现以下情形

B ... 1
A ... 0
B ... 1
.....
.....
A ... -1
A ... -2
A ... -3
A ... -4

这是因为多线程的虚假唤醒导致的,在多线程中判断必须使用while
如果使用if

 if (num != 0) {
// 假设此时有B,D线程在这里wait,如果被唤醒后,不会再次进行num != 0判断,这样就会导致num ++ 两次。如果使用while的话,线程被唤醒以后会再次进行条件判断
   this.wait();
 }
原文地址:https://www.cnblogs.com/amberbar/p/13290672.html