生產者與消費者案例 虛假喚醒

2021-09-07 18:35:33 字數 2663 閱讀 7352

以下是乙個案例,有乙個店員,負責進貨和賣貨。進貨生產,賣貨消費。

當商品超過10件,生產等待,消費繼續,當少於0件,消費等待,消費繼續。

正常**如下:

package

com.atguigu.juc;

/** 生產者和消費者案例 */

public

class

testproductorandconsumer }//

店員class

clerk

catch

(interruptedexception e)

}system.out.println(thread.currentthread().getname() + " : " + ++product);

this

.notifyall();

}//賣貨

public

synchronized

void sale()

catch

(interruptedexception e)

}system.out.println(thread.currentthread().getname() + " : " + --product);

this

.notifyall();

}}//

生產者class productor implements

runnable

@override

public

void

run() catch(interruptedexception e)clerk.get();

}}}//

消費者class consumer implements

runnable

@override

public

void

run() }}

執行結果:

很和諧沒問題!,生產者每次生產完就等待一下,導致消費者搶到資源,這樣導致:0,1輪替。

但是,如果此時再假如乙個生產者和消費者:

public

class

testproductorandconsumer

}

此時執行結果:

可以看到,非常離譜!生產者數量為負數,並且一直沒有停止的樣子。

分析:假如最開始是缺貨狀態,消費者b和d進入都是進入等待的,此時乙個生產者搶到資源,進行生產,完事生產了一件,

兩個消費者同時喚醒,喚醒了之後,每個消費者都繼續下面**,也就是wait下面的--product,導致數量為負數。

這個時候兩個消費者再次進入當然還是等待,乙個生產者再次進入,當然效果和上面一樣,再次數量在-1的基礎上,-1,-2。

為了解決這個,其實jdk中已經說明了,對於wait方法的使用,必須始終放在while迴圈中。

每次執行緒被喚醒之後都得重新進入迴圈,而不是直接執行下面的--或者++操作。

修改如下:

把上面的if換成while即可:

package

com.atguigu.juc;

/** 生產者和消費者案例 */

public

class

testproductorandconsumer }//

店員class

clerk

catch

(interruptedexception e)

}system.out.println(thread.currentthread().getname() + " : " + ++product);

this

.notifyall();

}//賣貨

public

synchronized

void sale()

catch

(interruptedexception e)

}system.out.println(thread.currentthread().getname() + " : " + --product);

this

.notifyall();

}}//

生產者class productor implements

runnable

@override

public

void

run()

catch

(interruptedexception e)

clerk.get();

}}}//

消費者class consumer implements

生產者與消費者的虛假喚醒問題

什麼是虛假喚醒?當乙個條件滿足時,喚醒了多個執行緒,其中部分執行緒不能被執行卻執行了 比如操作乙個變數 number初始是0,執行緒a對number進行 1,執行緒b對number進行 1,現在沒有問題。但是,再有執行緒c對number進行 1和執行緒d對number進行 1時,就會出現不只是0和1...

生產者消費者模式之虛假喚醒

當出現虛假喚醒時,解決方法 將if判斷改為while迴圈。在弄懂虛假喚醒之前,先了解兩個定義 1 重入 重入 意味著獲取鎖的操作的粒度是 執行緒 而不是 呼叫 2 執行緒的生命週期 執行緒狀態圖 當我們只有兩個執行緒的時候,即 a 生產者 和 b 消費者 整個模式不會出現問題,當增加兩個執行緒 c ...

生產者與消費者案例

手頭有兩個人 也就是兩個類 乙個做存操作,乙個做取操作,並且只有當存完或者取完方可進行令乙個操作。以此達到迴圈輸出的訪問操作。第一步 先寫測試生產者類與消費者類 和 執行緒操作msg類 生產者 public class product implements runnable override pub...