![](/img/trans.png)
[英]Signal running thread1 to complete method1 after thread2 enters method2
[英]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
變量時對其他線程可見。
* 編輯:我添加了“隨后”以明確表示synchronized
和volatile
都不足以確保線程將以某種特定順序訪問var
。 如果您希望確保線程 2在線程 1 分配它之前不會嘗試讀取var
,那么您將不得不使用其他一些方法†來協調它們的活動。 正確使用synchronized
或volatile
只能確保IF線程 1 在線程 2 檢查之前更新var
,然后線程 2 會看到更新。
† 有很多“其他方式”。 一個例子是Semaphore
。 線程 1 可以在更新var
后release()
信號量的許可,線程 2 可以在讀取var
之前acquire()
許可。 如果在線程 1 完成其工作之前到達信號量, acquire()
調用將導致線程 2 等待。
如果你不讓 'var' 易失,那么在寫入和讀取 'var' 之間就沒有發生之前的邊緣。 所以你手上有一個數據競賽,奇怪的事情可能會發生,比如編譯器把事情搞砸了。
簡而言之:使其易失(或確保您使用相同的鎖讀取“var”)。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.