2012-07-17 38 views
19

我有以下鎖聲明:應該聲明一個鎖定變量是否爲volatile?

private readonly object ownerLock_ = new object(); 

lock (ownerLock_) 
{ 
} 

我應該使用volatile關鍵字爲我的鎖變量?

private readonly volatile object ownerLock_ = new object(); 

在MSDN上,我看到它通常用於無鎖定訪問的字段,所以如果我使用鎖定,我不需要使用易失性?

MSDN

揮發性改性劑通常被用於由 多個線程,而不使用鎖定語句來串行訪問訪問的字段。

+0

我們需要更多的上下文來回答這個問題。與使用鎖的對象相關的鎖存在哪裏? – 2012-07-17 13:00:35

+3

它當前存在的線程絕對是安全的。當您在鎖定塊中添加代碼時,無法保證。 – 2012-07-17 13:00:55

+0

你不應該需要鎖定只讀對象,因爲它是隻讀的... – NominSim 2012-07-17 13:01:16

回答

18

如果你只有史以來訪問數據的鎖「衛士」,而你自己的鎖,然後是 - 使這些領域的揮發是多餘的。您不需要使ownerLock_變量易變。 (您目前沒有在lock聲明中顯示任何實際代碼,這使得很難具體說明 - 但我假設您會實際上正在讀取/修改lock聲明中的某些數據。)

volatile應該是很少用在應用程序代碼中。如果你想鎖定一個變量,那麼Interlocked幾乎總是比較簡單。如果你想要超越這個鎖無鎖訪問,我幾乎總是會開始鎖定。 (或嘗試使用不可變的數據結構來開始。)

我只希望在代碼中看到volatile,該代碼正嘗試爲線程構建更高級別的抽象 - 例如在TPL代碼庫中。這真的是一個專家的工具,它真的可以深入瞭解.NET內存模型...其中有很少的,IMO。

+0

感謝您的快速回復,可以說我只使用鎖定,這似乎很少見,但是可以使用2個鎖定語句的線程同時檢查ownerLock_狀態並嘗試鎖定它或彼此?我問這個問題是因爲我的代碼中存在鎖定問題,我認爲它與此問題有關。 – 2012-07-17 13:13:27

+0

@DorCohen:一次只有其中一人獲得鎖定。然後它將執行'lock'語句的主體,當它釋放鎖時,另一個線程將能夠獲取鎖並執行代碼。 – 2012-07-17 13:15:17

+0

@DorCohen,你的問題似乎不在於你鎖定的內容,而是你想要在鎖體內做什麼。 – 2012-07-17 13:16:12

2

如果是readonly它是線程安全的,句號。 (嗯,差不多可能能夠弄清楚如何在你的lock聲明中得到一個NullReferenceException,但這並不容易。)使用readonly你不需要volatile,Interlocked或鎖定。這是多線程的理想關鍵字,您應該儘可能使用它。對於一個鎖定對象來說它很有用,因爲它有很大的缺點(你不能改變這個值)並不重要。

此外,雖然參考是不可變的,但引用的對象可能不是。 「新對象()」在這裏,但如果它是List或其他可變的 - 而不是線程安全的 - 想要鎖定引用(以及所有其他引用,如果有的話)以保持該對象一次改變兩個線程。

相關問題