2011-03-06 50 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#

相关问题