是“双重检查锁定是破碎”只有java的东西?

http://www.cs.umd.edu/~pugh/java/memoryModel/DoubleCheckedLocking.html上的页面说,双重检查锁定在java中是有缺陷的。 我只是想知道它是否也适用于其他语言(C#,Vb,C ++等)

我读过双重检查锁定模式:是否破碎? , 这是双重检查锁定? , 如何解决Java中的“双重检查已破坏”声明? 说实话,我不知道共同的共识是什么。 有人说是的,其他人说不。

无论如何,我的问题是它是否也适用于其他语言(C#,Vb,C ++等)

双重检查锁定在Java中是安全的,提供:

  1. 实例变量声明为volatile ,AND
  2. JVM正确实现了JSR-133规范; 即它符合Java 5及更高版本。

我的来源是JSR-133(Java内存模型)常见问题 – Jeremy Manson和Brian Goetz,2004年2月 。 Goetz在其他许多地方都证实了这一点。

然而,正如格茨所说,这是一个时间已经过去的成语。 Java中的无对称同步现在很快,因此他建议您在需要进行延迟初始化时将getInstance()方法声明为synchronized 。 (我想这也适用于其他语言……)

此外,在所有条件相同的情况下,编写在Java 5中工作但在旧JVM中不可靠的代码是一个坏主意。


好的,那么其他语言呢? 嗯,这取决于成语的实现方式,通常在平台上。

  • C# – 根据https://stackoverflow.com/a/1964832/139985 ,它是平台相关的,实例变量是否需要是volatile。 但是, 维基百科说,如果你确实使用了volatile或显性内存障碍,那么这个习语就可以安全地实现。

  • VB – 根据维基百科 ,可以使用显式内存屏障安全地实现习语。

  • C ++ – 根据维基百科 ,可以使用Visual C ++ 2005中的volatile安全地实现这个习惯用法。但是其他消息来源说, 一般来说 ,C ++语言规范并不能为volatile提供足够的保证。 但是,双重检查锁定可以在C ++ 2011语言版本的上下文中实现 – https://stackoverflow.com/a/6099828/139985

(注意:我只是总结了一些我认为最近才发现的来源……声音。我不是C ++,C#或VB专家。请阅读链接页面并做出自己的判断。)

这篇维基百科文章涵盖java,c ++和.net(c#/ vb) http://en.wikipedia.org/wiki/Double-checked_locking

这是一个棘手的问题,有一个相互矛盾的信息的矿场。

问题的一部分是有一些双重检查锁定的变体:

  • 在快速路径上检查的字段可能是易失性的。
  • 存在单场变体和双重检查锁定的双场变体。

不仅如此,不同的作者对于模式“正确”的含义有不同的定义。

  • 定义#1 :广泛接受的编程语言规范(例如ECMA for C#)保证模式正确。
  • 定义#2 :该模式在特定体系结构(通常为x86)上实际工作。

尽管看起来很不愉快,但很多代码依赖于定义#2。

我们以C#为例。 在C#中,当且仅当字段是易失性时,根据定义#1,双重检查模式(如通常实现的)是正确的。 但是如果我们考虑定义#2,几乎所有变体在X86上都是正确的(即碰巧工作),即使该字段是非易失性的。 在Itanium上,如果字段是非易失性的,则单字段变体适用,但不是双字段变体。

不幸的后果是,你会发现文章对这种模式的正确性做出了明显矛盾的陈述。

正如其他人所说,这个成语已经有了时间。 FWIW,对于延迟初始化,。Net现在提供了一个内置类: System.Lazy (msdn) 。 不知道java中是否有类似的东西可用。

它在Java中存在缺陷,它在Java 5中被修复。事实被打破了更多的是实现问题加上误解而不是技术上的“坏主意”。