c# - 为什么这种双重检查锁定是正确的? (。网)

标签 c# concurrency locking thread-safety singleton

我已经阅读了很多关于双重检查锁定的危险的文章,我会努力远离它,但话虽如此,我认为他们的阅读非常有趣。

我正在阅读 Joe Duffy 的这篇关于使用双重检查锁定实现单例的文章: http://www.bluebytesoftware.com/blog/PermaLink,guid,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 可能没那么好。

关于c# - 为什么这种双重检查锁定是正确的? (。网),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8350713/

相关文章:

java - 在不阻塞主线程的情况下检索 HTTP 响应

c++ - POSIX部分写入,线程安全性和锁定

c# - 使用 MVC5 允许来自不同域的帧

c# - 创建一个从父属性继承的环境属性

c# - 从 XPath 中检索与同一节点中的另一个属性值相匹配的属性值

c# - 如何将 SslStream/AuthenticateAsServer 与自签名证书/ key 一起使用?

Java 线程优先级

c++ - DLL 如何处理来自多个进程的并发?

.net - .NET 中的跨进程读写同步原语?

c# - 什么时候锁定类型是个好主意?