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 ++等)
答案 0 :(得分:9)
双重检查锁定在Java中是安全的,提供:
volatile
,AND 我的来源是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)
这是一个棘手的问题,那里有一个相互矛盾的信息。
问题的一部分是有一些双重检查锁定的变种:
不仅如此,不同的作者对于模式“正确”的含义有不同的定义。
尽管看起来很不愉快,但很多代码依赖于定义#2。
我们以C#为例。在C#中,当且仅当字段是易失性时,根据定义#1,双重检查模式(如通常实现的)是正确的。但是如果我们考虑定义#2,几乎所有变体在X86上都是正确的(即碰巧工作),即使该字段是非易失性的。在Itanium上,如果字段是非易失性的,则单字段变体适用,但不是双字段变体。
不幸的结果是,你会发现文章对这种模式的正确性做出了明显矛盾的陈述。
答案 3 :(得分:2)
正如其他人所说,这个成语已经有了时间。 FWIW,对于延迟初始化,。Net现在提供了一个内置类:System.Lazy<T>
(msdn)。不知道java中是否有相似之处。
答案 4 :(得分:1)
它在Java中存在缺陷,它已在Java 5中得到修复。事实被破坏的更多是一个实现问题,加上误解而不是技术上的“坏主意”。