3 回答

TA貢獻1784條經驗 獲得超7個贊
基本上,您在這里嘗試做的是valueSet用作布爾標志來同步Consumer和Producer-- 使它們依次工作。真的,valueSet只能在一瞬間是真的或假的;然而,這不是兩個線程(消費者和生產者)如何看待它。
我們知道在 Java 中,對象存儲在堆上;那就是所謂的主存。但是,對于每個線程,出于性能考慮,對所用對象的引用都保存在特定于線程的緩存中。如在這里,Producer和Consumer共享一個Item被存儲在堆上對象; 該字段item.valueSet可能被每個線程緩存。
_______________ ______________
| Consumer | | Producer |
| _________ | | _________ |
| | | | | | | |
| | Cache1 | | | | Cache2 | |
| | valueSet| | | | valueSet| |
| |_________| | | |_________| |
|_______________| |______________|
| | | |
| | | |
_|_|______________|_|__
| |
| MAIN MEMORY |
| valueSet |
|_______________________|
例如,當Consumer更改valueSet為 時false,它可能會也可能不會將新值刷新到主內存;類似地,當Producer檢查時valueSet,它可能會也可能不會嘗試從主內存中讀取最新值。這就是volatile關鍵字發揮作用的地方。當您設置valueSet為 時volatile,它確保兩個線程向/從主內存寫入/讀取最新值。
請注意,上面的總結基本上被稱為JVM 內存模型。它是一組規則,用于定義多線程情況下 JVM 的行為。
如果您嘗試更改代碼的以下部分:
**volatile** boolean valueSet = false ;
**volatile** int item = 0 ;
...
item.produce((int)(Math.random()*100)) ; // added parenthesis
您將看到以下輸出:
Started producer and consumer threads :
Consuming !
Producing ....
Produced : 83
Producing ....
Consumed : 83
Consuming !
Produced : 54
Producing ....
Consumed : 54
Consuming !
Produced : 9
Producing ....
Consumed : 9
Consuming !
Produced : 23
Producing ....
Consumed : 23

TA貢獻2037條經驗 獲得超6個贊
首先,您需要創建共享變量volatile
。
允許線程將其局部變量放在寄存器中,所以是的,一個線程可以將其valueSet
視為 false,而另一個線程可以將其視為true
. 同時。使變量volatile
強制每次都從內存中讀取。
但是,這并不能保證代碼沒有其他問題。同步可能很棘手。但是研究volatile
以克服最可能的原因。
添加回答
舉報