为什么这种双重检查的锁定是正确的? (.网) [英] Why is this double-checked locking correct? (.NET)

查看:80
本文介绍了为什么这种双重检查的锁定是正确的? (.网)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我已经阅读了很多有关双重检查锁定的危险的信息,并且我会尽力避免这种情况,但是我说,他们认为这很有趣.

I have read a lot about the dangers of double checked locking and I would try hard to stay away of it, but with that said I think they make a very interesting read.

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

I was reading this article of Joe Duffy about implementing singleton with double checked locking: http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx

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

And the (variant of) solution he seemed to propose is this:

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;
    }
}

}

我的问题是,那还不存在写被重新排序的危险吗?特别是这两行:

My question is, doesn't that still have the danger of writes being reordered? Specifically these two lines:

instance = new Singleton();
initialized = 1;

如果这些写操作被颠倒了,那么其他一些线程仍然可以读取空值.

If those writes are inverted, then some other thread can still read null.

推荐答案

我认为关键在链接的文章中(

I think the key is in the linked article (http://msdn.microsoft.com/en-us/magazine/cc163715.aspx#S5). Specifically that the MS-implemented .NET 2.0 memory model has the following property:

写入不能从同一线程移至其他写入.

Writes cannot move past other writes from the same thread.

达菲提到在IA-64上做了很多工作来支持这一点:

Duffy mentions that a lot of work was done to support this on the IA-64:

我们通过确保写入通过st.rel指令在IA-64上具有释放"语义来实现此目的.单个st.rel x保证至少在x的新值对另一个逻辑处理器可见之前,每个逻辑处理器似乎已经发生了导致其执行(在物理指令流中)的任何其他加载和存储.可以通过ld.acq指令为加载赋予获取"语义,这意味着在ld.acq x之后发生的任何其他加载和存储似乎都不会在加载之前发生.

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.

请注意,达菲还提到这是针对MS的保证-它不属于ECMA规范(至少在2006年撰写本文时).因此,Mono可能不会那么好.

Note that Duffy also mentions that this is an MS-specific guarantee - it's not part of the ECMA spec (at least as of the the article's writing in 2006). So, Mono might not be as nice.

这篇关于为什么这种双重检查的锁定是正确的? (.网)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆