DCL是否仍然损坏? [英] Is DCL still broken?

查看:71
本文介绍了DCL是否仍然损坏?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

据我了解,使用旧的JMM时,实现懒惰单调的DCL(双重检查锁定)技巧被打破了,但我坚信,新的JMM和易失性字段已修复了该问题...

但是在中一篇不错的文章,显然很新,足以引用DCL中的新旧JMM和volatile字段,表明它仍然坏了...

在这里,我读到它是固定的,然后我发现了这一点……有人可以最后说它是否损坏了?

我的理解是,通过在关系发生前先确保其波动性并有效地发行成员来解决问题,DCL现在就有效了……虽然我同意静态惰性初始化是可取的并且更易于理解...

解决方案

在这里,我读到它是固定的,然后我发现了这一点……有人可以最后说它是否损坏了?

这取决于您所说的它".

如果您问是否可以使用volatile进行DCL,那么答案是肯定的,发布Java5.(volatile的原始语义没有很好定义,这意味着使用volatile并不是修复,Java 5之前的版本.)

如果您问是否可以在没有volatile的情况下进行DCL,那么答案是否定的.Java5内存模型更改不会使用非易失性instance变量修复" DCL的原始Java实现./p>

如果您要问是否将DCL用于延迟初始化的单例仍然是一个好主意,那么答案是否定的(我认为):

  • 有更好的方法来实现延迟初始化的单例.使用enum是其中之一.

  • 由于DCL习惯用法仍然容易出错且不易理解 1 ,因此最好避免使用它.

  • 同步性能的改进已大大消除了对DCL的需求.


枚举和静态init将在类加载时初始化单调(如果我输入错误,请纠正我).

我认为你错了.类的初始化也很懒.除非您强制执行,否则它不会在上课加载时发生.例如通过使用 JLS 12.4.1 设置确定何时发生的规则.

结果是,您可以确保基于枚举的单例的初始化发生得很懒,并且绝对可以安全地完成.

顺便说一句,对延迟初始化的硬性要求向我暗示了您的应用程序设计中的问题.至少,它引入了脆弱性……无论如何实现延迟初始化.


1-如果普通的Joe程序员"不理解DCL的复杂性,那么在他可能需要维护的代码中使用DCL是一个坏主意.您比普通的Joe程序员更聪明的事实无济于事.

As far as I understand with old JMM the DCL (Double checked Locking) trick to implement lazy singletone was broken, but i tought that it was fixed with new JMM and volatile field...

However in this nice article which is obviously new enought to refer new and old JMM and volatile field in DCL states that it is still broken...

Here and there i read that it is fixed then i discover this... Can someone just say finally is it broken or not?

My understanding is that with volatile guaranteeing the hapens before relationship and effectively issuing a membar solves issue and DCL is valid now... altough i agree that static lazy init is preferable and easyer to understand...

解决方案

Here and there i read that it is fixed then i discover this... Can someone just say finally is it broken or not?

It depends on what you mean by "it".

If you are asking if you can do DCL with a volatile then the answer is Yes, post Java 5. (The original semantics of volatile were not well defined, which meant that using a volatile wasn't a fix, pre Java 5.)

If you are asking if you can do DCL without a volatile then the answer is No. The Java 5 memory model changes don't "fix" the original Java implementation of DCL with a non-volatile instance variable.

If you are asking if it is still a good idea to use DCL for lazy initialized singletons, then the answer is No. (In my opinion):

  • There are better ways to implement a lazily initialized singleton. Using an enum is one of them.

  • Since the DCL idiom is still error prone and not well understood1, it is better to avoid it.

  • Synchronization performance improvements have largely removed the need for DCL.


Enum and static init will initialize the singletone on class load (correct me if i'm mistaken).

I think that you are mistaken. Class initialization is also lazy. It doesn't happen at class load time unless you force it; e.g. by using the 3-arg overload of Class.forName. JLS 12.4.1 sets out the rules that determine when it occurs.

The upshot is that you can ensure that initialization of an enum-based singleton happens lazily, and it will definitely be done safely.

As an aside, a hard requirement for lazy initialization is suggestive to me of a problem in your application design. At the very least, it introduces a point of fragility ... no matter how the lazy initialization is implemented.


1 - If an "average Joe programmer" doesn't understand the intricacies of DCL, then it is a bad idea to use DCL in code that he might need to maintain. The fact that you are smarter than the average Joe programmer is moot.

这篇关于DCL是否仍然损坏?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆