所谓锁定助手,是指可以通过using
语句实现锁定的一次性对象。例如,考虑使用Jon Skeet's MiscUtil中的SyncLock
类的典型用法:
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
}
}
}
现在,考虑以下用法:
var example = new Example();
new Thread(example.ConcurrentMethod).Start();
我的问题是这样的——由于
example
在一个线程上创建,而ConcurrentMethod
在另一个线程上调用,那么ConcurrentMethod
的线程是否可能对构造函数中_padlock
的赋值毫不知情(由于线程缓存/读写重排序),从而抛出NullReferenceException
(在_padLock
本身上)?我知道使用
Monitor
/lock
进行锁定具有内存屏障的好处,但是使用此类锁辅助程序时,我看不到为什么可以保证这样的屏障。在这种情况下,据我所知,必须修改构造函数:public Example()
{
_padlock = new SyncLock();
Thread.MemoryBarrier();
}
编辑 Hans Passant认为创建线程意味着存在内存屏障。那么如何处理:
var example = new Example();
ThreadPool.QueueUserWorkItem(s => example.ConcurrentMethod());
现在,线程不一定是在调用start()方法时就创建了...
_padLock
引用不会改变,因此缓存是无关紧要的。第一次读取将在设置后发生。如果它是按需创建或其他什么的话,你的问题可能更有价值。 - H H