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

时间:2011-05-11 03:01:42

标签: c# java vb.net multithreading synchronization

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

我看过Double checked locking pattern: Broken or not?Is this broken double checked locking?How to solve the "Double-Checked Locking is Broken" Declaration in Java?是真实的,我不知道共同的共识是什么。有人说是的,其他人说没有。

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

5 个答案:

答案 0 :(得分:9)

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

  1. 实例变量声明为volatile,AND
  2. JVM正确实现了JSR-133规范;即它符合Java 5及更高版本。
  3. 我的来源是JSR-133 (Java Memory Model) FAQ - Jeremy Manson and Brian Goetz, February 2004。 Goetz在其他许多地方都证实了这一点。

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

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


    好的,那么其他语言怎么样?嗯,这取决于如何实现成语,并且通常在平台上。

    • C# - 根据https://stackoverflow.com/a/1964832/139985,它是平台相关的,实例变量是否需要是易失性的。但是,Wikipedia表示如果您使用volatile或明确的内存障碍,则可以安全地实施该习惯用法。

    • VB - 根据Wikipedia,可以使用显式记忆障碍安全地实现习语。

    • C ++ - 根据Wikipedia,可以使用Visual C ++ 2005中的volatile安全地实现成语。但是其他来源说一般 C ++语言规范没有为volatile提供足够的保证。但是,双重检查锁定可以在C ++ 2011语言修订版本的上下文中实现 - https://stackoverflow.com/a/6099828/139985

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

答案 1 :(得分:3)

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

答案 2 :(得分:3)

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

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

  • 快速路径上检查的字段可能不稳定。
  • 有一个单字段变体和双字段锁定的双字段变体。

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

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

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

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

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

答案 3 :(得分:2)

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

答案 4 :(得分:1)

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