据我所知,使用旧的JMM来实现懒惰单调的DCL(双重检查锁定)技巧被打破了,但是我坚信它已被新的JMM和volatile字段所修复...
但是,在this不错的文章中,这显然已经足够新,足以引用DCL中的新旧JMM和volatile字段,表明它仍然坏了...
我在这里到那里读到它是固定的,然后我发现了这一点……有人可以最后说它是否损坏了?
我的理解是,通过波动性地在关系发生之前保证发生的先兆并有效地发出问题可以解决问题,并且DCL现在是有效的。。。。。
最佳答案
我在这里到那里读到它是固定的,然后我发现了这一点……有人可以最后说它是否损坏了?
这取决于您所说的“它”。
如果您问是否可以使用volatile进行DCL,那么答案是是的,发布Java5。(volatile
的原始语义没有得到很好的定义,这意味着使用volatile
不是一个解决方案,请先Java 5.)
如果您询问是否可以在不使用volatile的情况下进行DCL,那么答案是“否”。Java 5内存模型更改不会使用非易失性instance
变量“修复” DCL的原始Java实现。
如果您要问是否将DCL用于延迟初始化的单例仍然是一个好主意,那么答案是否定的(我认为):
有更好的方法来实现延迟初始化的单例。使用enum
是其中之一。
由于DCL习惯用法仍然容易出错且不太了解1,因此最好避免这种情况。
同步性能的提高很大程度上消除了对DCL的需求。
枚举和静态init将在类加载时初始化单调(如果我输入错误,请纠正我)。
我想,那你就错了。类的初始化也很懒。除非您强制执行,否则它不会在上课时发生。例如通过使用Class.forName
的3-arg overload。 JLS 12.4.1设置确定何时发生的规则。
结果是您可以确保基于枚举的单例的初始化发生得很懒,并且绝对可以安全地完成。
顺便说一句,对延迟初始化的严格要求使我想到您的应用程序设计中存在问题。至少,它引入了脆弱性……无论如何实现延迟初始化。
1-如果“普通的Joe程序员”不了解DCL的复杂性,那么在他可能需要维护的代码中使用DCL是一个坏主意。您比普通的Joe程序员更聪明的事实是没有意义的。