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

2024-04-09

我读过很多关于双重检查锁定的危险的文章,我会尽力避免它,但话虽如此,我认为他们读起来非常有趣。

我正在阅读 Joe Duffy 的这篇关于使用双重检查锁定实现单例的文章:http://www.bluebytesoftware.com/blog/PermaLink,guid,543d89ad-8d57-4a51-b7c9-a821e3992bf6.aspx 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 http://msdn.microsoft.com/en-us/magazine/cc163715.aspx#S5)。具体来说,MS 实现的 .NET 2.0 内存模型具有以下属性:

写入操作不能超过同一线程的其他写入操作。

Duffy 提到,为了在 IA-64 上支持这一点,我们做了很多工作:

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

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

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

为什么这种双重检查锁定是正确的? (。网) 的相关文章

随机推荐

  • PKCS11异常:CKR_KEY_FUNCTION_NOT_PERMITTED

    你看 我有一个小程序 可以根据RSA在 pkcs11 令牌中找到的私钥 在巴西 现在有一些包含 2048 位私钥的新证书 也有常规 1024 位的旧型号 到目前为止 我的应用程序运行良好 我使用的是 1024 位证书 所以不用担心 但现在我
  • 使用 !== 或 != 将 Julia 变量与 `nothing` 进行比较

    在一些 Julia 代码中 何时可以看到条件表达式 例如 if val nothing dosomething end where val是一个类型变量Union Int Nothing 条件有什么区别val nothing and val
  • 返回布尔值和字符串值的最佳实践是什么

    我创建了一个方法 该方法对 XML 层次结构执行一些验证 该层次结构是在运行时由 Javascript 文本中的另一个类动态生成的 我的方法当前返回 True 或 False 这对使用我的类的任何人都有帮助 但我还想返回更多信息 因为可能有
  • CreateRemoteThread 返回 ERROR_ACCESS_DENIED - Windows 7 DLL 注入

    我正在尝试编写一个使用CreateRemoteThread注入一个dll 问题是 CreateRemoteThread 拒绝工作 GetLastError 返回 5 即 ERROR ACCESS DENIED 我不明白为什么 我正在根据这个
  • SNMP 错误,端口已在使用中

    我创建了一个 SNMP 代理模拟器应用程序 它对模拟设备使用端口号 161 有时会出现端口已使用异常 如何知道161端口是否繁忙 只需启动您的应用程序即可 如果它收到 BindException 则该端口正在使用中 如果没有 您的应用程序可
  • 如何在设定时间后关闭 ProgressDialog?

    我试图在 3 秒后自动关闭 ProgressDialog 框 这是对话框 ProgressDialog progress new ProgressDialog this progress setTitle Connecting progre
  • 如何在C#中通过解析Xml创建表达式树?

    我希望通过使用 C 解析 xml 来创建表达式树 xml 如下所示
  • 如何创建历史事实表?

    我的数据仓库中有一些实体 Person 具有 personId dateFrom dateTo 和其他可以更改的属性 例如姓氏 出生日期等 缓慢变化的维度 Document 文档 ID 编号 类型 Address 地址 ID 城市 街道 房
  • 阻止 Hibernate 创建非空约束

    有没有办法阻止 Hibernate 为带有注释的属性创建非空约束 javax validation constraints NotNull使用时hbm2ddl create 来自 Hibernate Validator 的文档 6 1 数据
  • 对包含空标记的字符串进行标记

    我有一个看似简单的问题 就是用逗号分隔String到令牌中 在以下情况下输出应包含空令牌 中的第一个字符String是一个逗号 中的最后一个字符String是一个逗号 出现两个连续的逗号 例如 对于String abd def ghi 应该
  • Java XMLGregorianCalendar 转换为 Java util.Date 时存在错误?

    我正在将日期 时间值写入 XML 文件 方法是从基于 RAP 的 UI 中读取日期作为 Java Date 对象 并将其作为XMLGregorianCalendar反对实际的文件编写代码 相应的类是自动生成的 我无法控制它们 我输入的日期是
  • Java中String(String)构造函数的使用[重复]

    这个问题在这里已经有答案了 我读过的文章和书籍使用String s new String 应该一直避免 我明白为什么会这样 但是使用 String String 构造函数有什么用处吗 我认为不存在 也没有看到任何其他证据 但我想知道 SO
  • 层位置在(核心)动画开始时跳跃

    因此 我尝试创建一个平铺翻转效果 就像在 Windows Phone 7 上一样 到目前为止 我有以下代码 但我有几个疑问 CALayer layer self theRedSquare layer CATransform3D initia
  • C++ 函数导致应用程序崩溃且无法正常工作

    我的应用程序中出现了一个问题 我的 PrintAll 函数无法正常工作 最终只会使我的应用程序崩溃 我的应用程序应该从文件中读取字符串并将它们插入到数组中 问题是它读取不正确 最终会使我的应用程序崩溃 我认为问题出在这儿 int main
  • 如何使用绘图中的范围分隔符?

    我想使用plotly从某些图中的x轴中删除某些间隔 我找到了随附的示例https plotly com python time series https plotly com python time series 但运行它给了我错误 Val
  • 如何从 Twitter 的 firebase 用户获取 @user

    我试图在通过 firebase 登录 Twitter 后访问 Twitter 用户名 但 getDisplayName 方法返回用户名 而不是 有任何想法吗 我已经尝试过这个 FirebaseAuth getInstance getCurr
  • 如何找出一个类属于哪个依赖项?

    我正在使用 m2eclipse 我想在新项目中重用以前项目的一些依赖项 我知道我想使用哪个类 但我似乎无法找出它到底属于哪个依赖项 如果 eclipse 只是告诉我它从中加载的 jar 的名称 我会很高兴 我怀疑有一种方法可以在 Eclip
  • 如何获取字典中的键列表?

    我只想要字典的键而不是值 我还无法获得任何代码来执行此操作 事实证明 使用另一个数组的工作量太大 因为我也使用了删除 如何获取字典中的键列表 Use the Dictionary
  • int 可以别名为 unsigned int 吗? [复制]

    这个问题在这里已经有答案了 编译器生成代码假设int可以通过一个别名unsigned int 下面的代码 int f int a unsigned int b a 10 b 12 return a int f int a double b
  • 为什么这种双重检查锁定是正确的? (。网)

    我读过很多关于双重检查锁定的危险的文章 我会尽力避免它 但话虽如此 我认为他们读起来非常有趣 我正在阅读 Joe Duffy 的这篇关于使用双重检查锁定实现单例的文章 http www bluebytesoftware com blog P