Java Singleton

After going through a couple job interviews, I quickly realized that there are many differing “opinions” (yes even among seasoned Java programmers) about the best way to initialize a singleton class. For the record, there are really only two fundamental ways of initializing a singleton properly in java: eager or lazy. Then there is a neat trick to try to get the best of both worlds so that makes a total of three. Depending on the person you talk to, one of these methods may be preferred over the others but all three listed below are thread safe.

Eager Initialization

In eager initialization, the singleton is instantiated when the programs starts whether or not it gets used. The problem with this approach is that valuable resources are allocated whether or not they ever get used. If the singleton has a large memory footprint, this may not be a good choice.

Example 1. Eager Initialization

public class Singleton {

    // Eager initialization happens here.
    static private Singleton instance = new Singleton();

    // Prevent instantiation by public.
    private Singleton() {
    }

    public static Singleton getInstance() {
        return instance;
    }
}

Eager initialization relies on the fact that the JVM will initialize the class members upon loading the class. And the class is loaded when it is first referenced.

Lazy Initialization

On the other end of the spectrum, we have lazy initialization which the object only get instantiated on the first time the getInstance() method is called. This has the advantage of not allocating the resources unless it is actually needed.

The problem with this approach is that the getInstance() method needs to be synchronized. Therefore there is a performance hit when acquiring the singleton.

Example 2. Lazy Initialization

public class Singleton {

    static private Singleton instance = null;

    // Prevent instantiation by public.
    private Singleton() {
    }

    synchronized public static Singleton getInstance() {
        if (instance == null) {
            // Lazy initialization happens here
            // on the first call to this method.
            instance = new Singleton();
        }
        return instance;
    }
}

Do not try to circumvent the synchronized method by using a DCL (double check locking) mechanism as it does not work with the java memory model. Read more about that by following the resources links below.

Initialize-on-demand holder class idiom

There is one final way to get the best of both worlds and that is to use “Initialize-on-demand holder class” idiom which can be found in “Effective Java” by Joshua Bloch. This method relies on the JVM only intializing the class members upon first reference to the class. In this case, we have a inner class that is only referenced within the getInstance() method. This means SingletonHolder will get initialized on the first call to getInstance().

Example 3. Initialize-on-demand

public class Singleton {

    // Prevent instantiation by public.
    private Singleton() {
    }

    public static Singleton getInstance() {
        return SingletonHolder.instance;
    } 

    /**
     * Singleton implementation helper.
     */
    private static class SingletonHolder {
        // This gets initialized on first reference
        // to SingletonHolder.
        static final Singleton instance = new Singleton();
    }
}

Now the singleton object will not get allocated until it is used and we did not need to incur the overhead of a synchronized method call.

Happy programming,
Chiao

References and Resources

5 Responses

  1. David says:

    For initialize on demand, isn’t there the possibility that more than one thread may call getInstance() at the same time ?

    • chiao says:

      Yes, multiple threads can call getInstance() at the same time. But just like Eager Initialization, the thread safety comes from the fact that the singleton instance is ultimately held in a static variable. The JVM guarantees that static variables are only initialized once by the classloader, thus insuring that all threads calling getInstance() will return the same instance of the variable.

      The advantage for initialize-on-demand idiom is that the static variable is inside an inner class. The main Singleton class does not contain any static variables so eager instantiation will not take place.

    • David says:

      So if you have the same implementation as Initialize-on-demand with the difference being that class Singleton declares a static variable, than this approach wont work and it will not be thread safe ? For example:

      public class Singleton{

      private static final int example = 0; //static variable declared just for example

      private Singleton(){ }

      public static Singleton getInstance() {

      return SingletonHolder.instance;
      }

      private static class SingletonHolder {
      static final Singleton instance = new Singleton();
      }

      Thanks for your response.

    • chiao says:

      It will work either way. Any static variables inside the class will be guaranteed to be initialized only once and before they are used. Having other static variables inside the Singleton class does not affect the static “instance” variable inside the inner class. Of course, your variable “example” may not be thread-safe depending on how you use it. But “instance” is still thread safe.

  2. chiao says:

    Yup, that article talks about the possibility of using reflection to access private constructors in java. By doing so, you can circumvent the private access restriction. So there are ways to break your singleton pattern but if you wanted to break your own code, there are easier ways to do it. The only time this would be a problem in the real world would be a framework or something trying to access your singleton through reflection. That generally will not happen since a singleton by nature would be fairly custom.

    I personally have not seen anyone trying to hack their own singletons on purpose. Why go through the trouble of creating a singleton only to hack it into multiple instances? Might as well just create a regular class in the first place.

    So that article is not really a contradiction of thread-safe methods for creating singletons. The methods listed here are still thread-safe methods of creating a singleton. But it does not prevent you from using reflection to hack the singleton into multiple instances.

Leave a Reply