Multiple ways of creating a Singleton

by Prasanth Gullapalli

Singleton pattern is one of the most widely used design patterns. When a class is called Singleton, there is only one instance created for it and it forms the global point of contact. This is implemented by making the constructor private and getInstance() method is given the responsibility of providing the access to the singleton object created. This can be pretty straight forward when we work in a single threaded environment. But when we have multiple threads, ensuring single instance creation can be little trickier. In this article I will discuss the multiple ways of creating a Singleton Class

1. Eager instantiation
2. Double Checked Locking Idiom
3. Initialization-on-demand holder idiom
4. Enum Singletons

(1) Eager instantiation: This is the easiest of all to implement and works in all versions of Java:

public final class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {
    }

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

Let’s go over the code. Constructor is marked private as we don’t want others to create instances. As the Singleton gets referred for the first time in another class, it gets loaded into JVM and all the static variables gets initialized. As the class loading is guaranteed to be thread-safe, there will be no concurrency issues making this the easiest and cleaner approach 🙂

But, suppose the object is very large and have also other accessible static methods/fields that gets used before calling getInstance(), then it is better to go for lazy initialization. There is no point creating an object when it is not needed.

(2) Double Checked Locking Idiom:

class Singleton {

	private static volatile Singleton INSTANCE;

    public static Singleton getInstance() {
        if (INSTANCE == null) {
            synchronized(Singleton.class) {
                if (INSTANCE == null)
                    INSTANCE = new Singleton();
            }
        }
        return INSTANCE;
    }
}

This version works for Java 1.5+ versions. Let us discuss this in detail. Prior to Java 1.5, volatile modifier only guaranteed that any writes to the variables marked volatile will be immediately visible to the user. Suppose say we have a class like this:

class Singleton2 {

	private Dummy dummy;
	private static volatile Singleton2 INSTANCE;

	private Singleton2(){
		dummy = new Dummy();
	}

    public static Singleton2 getInstance() {
        if (INSTANCE == null) {
            synchronized(Singleton2.class) {
                if (INSTANCE == null)
                    INSTANCE = new Singleton2();
            }
        }
        return INSTANCE;
    }
}

Now say two threads, A and B are accessing getInstance(). Now as A enters into the synchronized block, here is what it does: Creates a Singleton object, runs it constructor to create a dummy object and then publishes the singleton object created to INSTANCE. As it is a volatile variable, the newly created object becomes visible for all threads. Now say thread B tries to access getInstance(), it sees the INSTANCE already created(as it is a volatile variable). But when it accesses the dummy object inside it, it is not guaranteed to see the right value of it. Note that we created instance by getting a lock over the class. If we get the same lock before trying to access the newly created object, we will properly see the initialized value of dummy.But in the absence of getting lock, we may see a partially constructed object.

In Java 1.5, JMM modified the semantics of volatile variable. All the state modifications that happen before the write to a volatile field as well will be published to the main memory. In other way, apart from making the write to a volatile variable immediately visible, the thread would also be able to see all the state(even nonvolatile instance variables) changes that happened before the write to a volatile variable. And hence after Java 1.5, the problem of seeing a partially constructed object would not be present. So the thread B would now be able to see the right value for dummy object.

But this is still not a good way to code. The whole point of double checked locking was to eliminate synchronization when not really needed. Prior to Java 1.5, volatile read was not so costly. But now it is more or less similar to using synchronization. So if the motto of using this approach was to get an improved performance, this really would not hep much. We can probably rely on the next approach for this.

(3) Initialization-on-demand holder idiom:

public final class Singleton {

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

    private Singleton() {
    }

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

We can use a private static class to load the instance. The instance gets created only when the class SingletonHolder is actually used. This not only takes care of the lazy instantiation but is also guaranteed to be thread safe.

However even after doing all this, there are few scenarios that we need to take care while implementing a class as Singleton.
1. Even private constructors can be accessed through Reflection. Here is an example of how to do it:

	public class Example {
		public static void main(final String[] args) throws Exception {
			Constructor constructor = Singleton.class.getDeclaredConstructor(new Class[0]);
			constructor.setAccessible(true);
			Singleton anotherSingletonInstance = constructor.newInstance(new Object[0]);
			System.out.println(anotherSingletonInstance);
		}
	}
	

For this sake we can throw an exception from constructor if an instance already exists.

	private Singleton() {
        if (SingletonHolder.INSTANCE != null) {
            throw new IllegalStateException("Already instantiated");
        }
		...
    }
	

2. We never want to create clones for Singleton. So there is no point in implementing Cloneable interface. If we are forced to implement it under certain unavoidable conditions, override the clone method to throw an UnsupportedOperationException

3. Suppose our class implements Serializable. The serialization mechanism creates a new instance every time we deserialize. So in order to avoid this override readResolve() method

	public final class Singleton implements Serializable{

		....

		@SuppressWarnings("unused")
		private Singleton readResolve() {
			return SingletonHolder.INSTANCE;
		}
	}
	

When our class overrides readResolve method, the object deserialized would be thwarted by the object returned in readResolve(). Hence the same instance gets returned even on deserializing it.

All the above three problems can be avoided by the following approach. This is suggested in Joshua Bloch’s Effective Java.

(4) Enum Singletons:

public enum Singleton {
   INSTANCE;
}

This looks a little hacky to me as we generally use enums to represent a set of constants. But of course this gives us the maximum benefits. It provides thread safety, ironclad guarantee against multiple instantiation even in the face of sophisticated serialization or reflection attacks. If lazy initialization is not needed, I feel the first approach is the best way to design a Singleton.

Advertisements

One thought on “Multiple ways of creating a Singleton

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s