写一个锁是否保证在另一个线程中读取新内容? (.Net,内存模型)

假设我有一个属性,其setter受锁保护,但没有任何锁定在getter周围,例如

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

除了同步写入(但不是读取)之外,锁定或者说Monitor.Exit应该导致易失性写入 。 我们现在说我们有两个线程A和B,并且发生以下序列:

  1. A读取MyProperty的当前值。
  2. B将新值写入MyProperty
  3. A再次读取MyProperty的当前值。

问:A现在可以保证看到新值吗? 或者我们的锁只是确保B及时写入主内存,而不是其他线程读取新值? 或者答案可能取决于我们是在运行.Net 2+还是“弱”的ECMA实施?

不,因为读取没有明确的内存屏障,所以不能“保证”看到新值。

您可以使用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(); } } } 

如果您在getter中使用Interlocked.Read,则应始终读取新值。 有关内存防护的更多信息,请参阅C#中的线程