我最近在Resharper网站上看到了以下帖子.这是对双重检查锁定的讨论,并具有以下代码:
public class Foo
{
private static volatile Foo instance;
private static readonly object padlock = new object();
public static Foo GetValue()
{
if (instance == null)
{
lock (padlock)
{
if (instance == null)
{
instance = new Foo();
instance.Init();
}
}
}
return instance;
}
private void Init()
{
...
}
}
Run Code Online (Sandbox Code Playgroud)
该帖子然后声称
如果我们假设Init()是用于初始化Foo状态的方法,那么由于内存模型不能保证读写顺序,上述代码可能无法按预期运行.因此,对Init()的调用实际上可能在变量实例处于一致状态之前发生.
这是我的问题:
我的理解是,.NET内存模型(至少从2.0开始)并没有要求instance被声明为volatile,因为lock它将提供一个完整的内存栅栏.是不是这样,还是我被误导了?
对于多个线程,是不是只对可观察的读/写重新排序?我的理解是,在一个线程上,副作用将是一致的顺序,并且lock就地防止任何其他线程观察到某些东西是不对的.我也在这里吗?
我正在使用 Monitor 类来管理关键部分。但有时我会遇到SynchronizationLockException以下消息
An unhandled exception of type 'System.Threading.SynchronizationLockException' occurred in ManagedType.dll
Additional information: Object synchronization method was called from an unsynchronized block of code.
Run Code Online (Sandbox Code Playgroud)
我的代码在下面
Object^ lockObj = gcnew Object(); //Global variable
bool GetValue()
{
try
{
Monitor::Enter(lockObj);
return this.value;
}
finally
{
Monitor::Exit(lockObj);
}
}
Run Code Online (Sandbox Code Playgroud)
在SynchronizationLockException抛出时Monitor::Exit(lockObj)调用。
我已经在这个论坛和互联网上搜索过,但包括 MSDN 在内的大多数主题都说“当您尝试在 Monitor.Enter() 和 Monitor.Exit() 中使用值类型变量而不是引用类型时,将抛出此异常”。
但就我而言,我使用 lockObj 作为引用对象。所以我不知道为什么它会抛出这个异常。有人可以帮助我吗?
非常感谢,
T&T集团!