【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間隔執行,可是多執行幾回就有可能會出現如下情形java

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();
 }
相關文章
相關標籤/搜索