0

What is the difference between thread-safe Singleton Design Pattern with Double Check Locking as in the below code.

public class Singleton {
    private static volatile Singleton instance;
    private Singleton() {}

    public static Singleton getInstance() {
        if (instance == null) {
            synchronized (this) {
                if(instance==null)
                    instance = new Singleton();
             }
        }
        return instance;
    }
}

And in below implementation other than Eager initialization.

public class Singleton {
    private static volatile Singleton instance = new Singleton();
    private Singleton() {}

    public static Singleton getInstance() {
        return instance;
    }
}
Justin Albano
  • 3,809
  • 2
  • 24
  • 51
Rizstien
  • 802
  • 1
  • 8
  • 23

1 Answers1

1

The Double-Check Locking (DCL) idiom is an attempt to instantiate a singleton object in a lazy manner, where the singleton object is not created until the first time it is needed. The problem with this approach is that it is flawed and does not work. For an in-depth understanding of why this idiom will not work, see:

While Brian Goetz goes into great detail about the reason for idiom failing, for the sake of brevity, the problem can be summed up in the following paragraph:

DCL relies on an unsynchronized use of the resource field. That appears to be harmless, but it is not. To see why, imagine that thread A is inside the synchronized block, executing the statement resource = new Resource(); while thread B is just entering getResource(). Consider the effect on memory of this initialization. Memory for the new Resource object will be allocated; the constructor for Resource will be called, initializing the member fields of the new object; and the field resource of SomeClass will be assigned a reference to the newly created object.

In short, the Java Memory Model (JMM) does not guarantee that given two threads, one will not see a partially constructed instance of the instance field, since the instance field is observed outside of a synchronized block (i.e., if (instance == null)).

Note that as of JDK 5, the double-checked locking idiom is possible, but it is still delicate and should be avoided whenever another alternative can be used.

The reason developers attempted to create the DCL idiom in the first place is that use of the synchronized keyword can result in a performance hit (according to Brian Goetz's article, as much as 100x).

The second pattern is a much simpler approach to the singleton pattern since it makes the singleton object static, which ensures that for all outside objects that attempt to access the singleton, only one object will ever be created. This approach is called eager instantiation because the instance object is created prior to any outside object needing it. Eager instantiation will usually suffice unless there is major overhead in creating the singleton object.

If lazy instantiation is required, a clever approach is to create a separate class with only the singleton instance as a static field:

public class Singleton {
    public static Singleton instance = new Singleton();
}

Since static fields are not initialized in Java until the class is loaded by the classloader, the instance object will not be instantiated until an outside object references the instance object. Thus, we have achieved lazy instantiation through the compiler and Java runtime environment.

Justin Albano
  • 3,809
  • 2
  • 24
  • 51
  • The first article points out in the end that as of JDK5 the semantics of volatile have changed and the pattern can be made to work. How to implement it properly is described at https://stackoverflow.com/questions/3578604/how-to-solve-the-double-checked-locking-is-broken-declaration-in-java – iluwatar Jul 04 '20 at 09:58
  • Thank you for the heads up. I've updated the answer to include a link to that correct DCL idiom implementation. – Justin Albano Jul 05 '20 at 11:56
  • @JustinAlbano that was really useful information but my original question intent was to ask "if there is anything wrong with 2nd implementation other than eager initialization ?" – Rizstien Jul 06 '20 at 01:42
  • No, there's nothing wrong with that implementation, although, the `volatile` keyword can be dropped. Since the singleton is a `static` value, it will be created only once by the Java runtime when the class is first loaded by the classloader, and therefore, the protection of the `volatile` keyword is not needed. – Justin Albano Jul 06 '20 at 11:34