加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

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

发布时间:2020-12-15 08:04:38 所属栏目:百科 来源:网络整理
导读:我已经阅读了很多关于双重检查锁定的危险,我会努力远离它,但据说,我认为它们是一个非常有趣的阅读. 我正在阅读Joe Duffy关于使用双重检查锁定实现单例的这篇文章: http://www.bluebytesoftware.com/blog/PermaLink,543d89ad-8d57-4a51-b7c9-a821e3992bf6.as
我已经阅读了很多关于双重检查锁定的危险,我会努力远离它,但据说,我认为它们是一个非常有趣的阅读.

我正在阅读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可能不那么好.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读