c# – 为什么这个双重检查锁定正确? (.净)

前端之家收集整理的这篇文章主要介绍了c# – 为什么这个双重检查锁定正确? (.净)前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我已经阅读了很多关于双重检查锁定的危险,我会努力远离它,但据说,我认为它们是一个非常有趣的阅读.

我正在阅读Joe Duffy关于使用双重检查锁定实现单例的这篇文章
http://www.bluebytesoftware.com/blog/PermaLink,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx

他似乎提出的(变体)解决方案是这样的:

class Singleton {
private static object slock = new object();
private static Singleton instance;
private static int initialized;
private Singleton() {}
public Instance {
    get {
        if (Thread.VolatileRead(ref initialized) == 0) {
            lock (slock) {
                if (initialized == 0) {
                    instance = new Singleton();
                    initialized = 1;
                }
            }
        }
        return instance;
    }
}

}

我的问题是,是否仍然存在写入重新排序的危险?具体来说这两行:

instance = new Singleton();
initialized = 1;

如果这些写入被反转,那么其他一些线程仍然可以读取null.

解决方法

我认为关键在于链接文章( http://msdn.microsoft.com/en-us/magazine/cc163715.aspx#S5).具体来说,MS实现的.NET 2.0内存模型具有以下属性

Writes cannot move past other writes from the same thread.

Duffy提到在IA-64上做了很多工作来支持这个:

We accomplish this by ensuring writes have ‘release’ semantics on IA-64,via the st.rel instruction. A single st.rel x guarantees that any other loads and stores leading up to its execution (in the physical instruction stream) must have appeared to have occurred to each logical processor at least by the time x’s new value becomes visible to another logical processor. Loads can be given ‘acquire’ semantics (via the ld.acq instruction),meaning that any other loads and stores that occur after a ld.acq x cannot appear to have occurred prior to the load.

请注意,Duffy还提到这是MS特定的保证 – 它不是ECMA规范的一部分(至少在2006年的文章撰写时).所以,Mono可能不那么好.

原文链接:https://www.f2er.com/csharp/100613.html

猜你在找的C#相关文章