By lock helpers I am referring to disposable objects with which locking can be implemented via using
statements. For example, consider a typical usage of the SyncLock
class from Jon Skeet's MiscUtil:
public class Example
{
private readonly SyncLock _padlock;
public Example()
{
_padlock = new SyncLock();
}
public void ConcurrentMethod()
{
using (_padlock.Lock())
{
// Now own the padlock - do concurrent stuff
}
}
}
Now, consider the following usage:
var example = new Example();
new Thread(example.ConcurrentMethod).Start();
My question is this - since example
is created on one thread and ConcurrentMethod
is called on another, couldn't ConcurrentMethod
's thread be oblivious to _padock
's assignment in the constructor (due to thread caching / read-write reordering), and thus throw a NullReferenceException
(on _padLock
itself) ?
I know that locking with Monitor
/lock
has the benefit of memory barriers, but when using lock helpers such as these I can't see why such barriers are guaranteed. In that case, as far as I understand, the constructor would have to be modified:
public Example()
{
_padlock = new SyncLock();
Thread.MemoryBarrier();
}
Source: Understanding the Impact of Low-Lock Techniques in Multithreaded Apps
EDIT Hans Passant suggests that the creation of a thread implies a memory barrier. So how about:
var example = new Example();
ThreadPool.QueueUserWorkItem(s => example.ConcurrentMethod());
Now a thread is not necessarily created...