簡體   English   中英

我們是否需要創建一個字段'volatile',如果 Thread1 進入同步塊,更新它,仍然在同步塊內,線程 2 在同步之外讀取字段?

[英]Do we need to make a field 'volatile', if Thread1 enters sync block, updates it, is still inside the sync block, Thread2 outside of sync reads field?

假設我們有一個“A 類”,它有一個數據成員“var”。

class A
{
  int var;

method()
{
read(var);

synchronized block
{

update var here;

}

}

假設線程 1 獲得鎖並進入同步塊。 它更新字段值“var”。 假設字段值由線程緩存在處理器的核心中。 它更新緩存中的值。

現在線程 2 開始運行,進入 method(),並讀取字段值 'var'。

線程 2,肯定會得到更新的值嗎? 是否同步確保線程 2 將獲得更新的值,即使線程 1 尚未退出同步。 在這種情況下,我們是否需要使 'var' 易變?

PS - 一切都發生在同一個對象上。

是否同步確保線程 2 將獲得更新的值

不,如果線程沒有進入synchronized塊, synchronized不會為線程做任何事情。 考慮synchronized的方法是這樣的:無論一個線程在離開同步塊之前做什么,都保證在第二個線程隨后*進入在同一個鎖對象上synchronized的塊時對其他線程可見。

對於單個int變量,您可以改為將其volatile volatile提供類似於synchronized的保證:無論一個線程在更新volatile變量之前做什么,都保證在第二個線程隨后*讀取相同的volatile變量時對其他線程可見。


* 編輯:我添加了“隨后”以明確表示synchronizedvolatile都不足以確保線程將以某種特定順序訪問var 如果您希望確保線程 2線程 1 分配它之前不會嘗試讀取var ,那么您將不得不使用其他一些方法†來協調它們的活動。 正確使用synchronizedvolatile只能確保IF線程 1 在線程 2 檢查之前更新var ,然后線程 2 會看到更新。

† 有很多“其他方式”。 一個例子是Semaphore 線程 1 可以在更新varrelease()信號量的許可,線程 2 可以在讀取var之前acquire()許可。 如果在線程 1 完成其工作之前到達信號量, acquire()調用將導致線程 2 等待。

如果你不讓 'var' 易失,那么在寫入和讀取 'var' 之間就沒有發生之前的邊緣。 所以你手上有一個數據競賽,奇怪的事情可能會發生,比如編譯器把事情搞砸了。

簡而言之:使其易失(或確保您使用相同的鎖讀取“var”)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM