2011-03-06 54 views
3

假設我有一個屬性,它的setter受鎖定保護,但沒有任何鎖定getter的鎖定,例如,圍繞寫入的鎖是否保證新讀取在另一個線程中? (.Net,內存模型)

private long _myField; 
public long MyProperty 
{ 
    get { return _myField; } 
    set { lock(whatever) _myField = value; } 
} 

除了同步寫入(但不讀取),鎖,或者更確切地說Monitor.Exit,應該引起volatile write。現在,讓我們說,我們有兩個線程A和B,以及下列順序發生:

  1. A讀取的MyProperty當前值。
  2. B爲MyProperty寫入新值。
  3. A再次讀取當前值MyProperty

問:A現在保證能看到新值嗎?或者我們的鎖是否確保B及時寫入主內存,但不是其他線程讀取新值?或者答案甚至可能取決於我們是運行在.Net 2+還是一個「較弱」的ECMA實施?

回答

3

不,因爲讀取沒有明確的內存屏障,所以不能「保證」看到新的值。

您可以使用ReaderWriterLockSlim來確保:a)寫入互相鎖定; b)讀取總是取得新值。

private readonly ReaderWriterLockSlim _myFieldLock = new ReaderWriterLockSlim(); 
private long _myField; 
public long MyProperty 
{ 
    get 
    { 
     _myFieldLock.EnterReadLock(); 
     try 
     { 
      return _myField; 
     } 
     finally 
     { 
      _myFieldLock.ExitReadLock(); 
     } 
    } 
    set 
    { 
     _myFieldLock.EnterWriteLock(); 
     try 
     { 
      _myField = value; 
     } 
     finally 
     { 
      _myFieldLock.ExitWriteLock(); 
     } 
    } 
} 
+0

注意:OP代碼'value = _myField'看起來像一個錯誤,因此我將其更改爲'_myField = value'。 – 2011-03-06 05:51:01

+1

RWLS有什麼意義? getter和setter中的lock關鍵字對於兩個線程也同樣適用,其中* lot *少開銷。 – 2011-03-06 05:56:04

+0

@ hans-passant如果有更多的線程在同一時間讀取,該怎麼辦? – 2011-03-06 05:56:57

1

如果您在getter中使用了Interlocked.Read,則應該始終讀取新值。有關內存隔離的更多信息,請參見Threading in C#

相關問題