Java Concurrency in Practice 聲明如下:當線程 A 執行一個同步塊,隨后線程 B 進入一個由同一個鎖保護的同步塊時,在釋放鎖之前對A 可見的變量值保證在獲取鎖時對 B 可見。換句話說,當 B 執行由同一鎖保護的同步塊時,A 在同步塊中或之前所做的一切對 B 都是可見的。沒有同步,就沒有這樣的保證。同樣的邏輯適用于 volatile 變量:volatile 變量的可見性影響超出了 volatile 變量本身的值。當線程 A 寫入一個 volatile 變量,隨后線程 B 讀取同一個變量時,在寫入 volatile 變量之前對 A 可見的所有變量的值在讀取該 volatile 變量后對 B 可見。從描述中可以清楚地看出,當您需要訪問某些共享狀態時,您可以使用這種可見性效果來實際替換(或限制使用)傳統鎖。在圖中的示例中,您可以看到線程 B 可以安全地讀取變量y,即使它在同步塊外的線程 A 中發生了更改。因此,當您在線程上鎖定之前更改某些共享狀態時使用它是否安全visibility guarantee,然后獲取鎖定,做某事(或者什么都不做,我猜),釋放鎖然后在另一個線程中獲得相同的鎖鎖定,釋放它,然后安全地從第一個線程中更新的共享變量中讀取最新值?
2 回答

揚帆大魚
TA貢獻1799條經驗 獲得超9個贊
引用語句中有一個關鍵部分:
volatile 變量的可見性影響超出了 volatile 變量本身的值。當線程 A 寫入一個 volatile 變量,隨后線程 B 讀取同一個變量時,在寫入 volatile 變量之前對 A 可見的所有變量的值在讀取 volatile 變量后對 B 可見。
雖然這顯然是正確的,但您在這里得到了關于 A 寫先于 B 閱讀的條件。然而,如果不鎖定,就無法保證讀/寫的順序——這就是重點。
所以你不能用 volatiles 替換每個同步,因為它不會產生相同的結果。

白板的微信
TA貢獻1883條經驗 獲得超3個贊
是的,您可以visibility guarantee
通過使用或任一形式的鎖定以描述的方式獲得,但volatile
僅此而已。具體來說,您不會獲得相互訪問和原子性。synchronized
另請參閱 JLS中有關 JVM的內存模型和happens-before關系的部分,以獲得更多細節和深度。
添加回答
舉報
0/150
提交
取消