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...