Does a lock around a write guarantee fresh read in another thread? (.Net, memory model)
Say I have a property whose setter is protected by a lock, but without any lock around the getter, e.g.
private long _myField;
public long MyProperty
{
get { return _myField; }
set { lock(whatever) _myField = value; }
}
In addition to synchronizing writes (but not reads), the lock, or rather Monitor.Exit, should cause a volatile write. Let's now say we have two threads A and B, and the following sequence happens:
- A reads the current value of
MyProperty
. - B writes a new value to
MyProperty
. - A reads the current value of
MyProperty
again.
Q: Is A now guaranteed to see the new value? Or did our lock just ensure that B writes to main memory in a timely manner开发者_如何转开发, but not that other threads read a fresh value? Or could the answer even depend on whether we're running in .Net 2+ or a "weaker" ECMA implementation?
No, since the read does not have the explicit memory barrier, it is not "guaranteed" to see the new value.
You can use a ReaderWriterLockSlim
to insure that a) the writes lock each other and b) the reads always pickup the new value.
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();
}
}
}
If you used Interlocked.Read in the getter you should always read the new value. See Threading in C# for more information about memory fences
精彩评论