问题
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...
回答1:
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.
回答2:
It was fixed in Java 5.
However these days the "correct" (i.e. the simplest) way is to use an enum for lazy initialization.
public enum Singleton {
INSTANCE;
// No need for a getInstance() method
//public static Singleton getInstance() {
// return INSTANCE;
//}
// Add methods to your liking
}
来源:https://stackoverflow.com/questions/31051353/is-dcl-still-broken