It is possible to implement double-checked locking (DCL) correctly in Java 5 and later. In Java 4 and earlier, it is not possible due to the fact that the behaviour of volatile
with respect to synchronization was not properly specified (and in practice was inadequate).
The code you included in your question is a correct implementation for DCL ... when run using a Java 5 JRE or later.
But (IMO), it is not worth using DCL. Especially if you (or developers coming after you) don't completely understand how to do it if correctly / safely.
The performance benefit is simply too small for this to be a worthwhile optimization in a real-life Java application. (And if it is, you are probably overusing / misusing singletons ... and that will bite you in other ways!)
Ok, so imagine that our SingletonDemo class has non-final field. So, concurrent thread will be able to read default value instead of correct value specified in constructor?
(The quoted JLS text is about an entirely different situation. It is about final
fields. It is not relevant here. And you cannot infer the behaviour for non-final
fields with synchronization from the behaviour of final
fields without synchronization.)
The answer to your question is No. The code in your question is doing enough to guarantee that a concurrent thread won't see the default value. To understand why, read the following:
- all of Section 17.4 of the JLS, and
- the last chapter of Goetz et al "Java Concurrency in Practice", which includes a section on DCL (if I remember correctly ...)