Singleton pattern inside out using Java

Posted: January 15, 2014 in linux, ubuntu
Tags: , ,
  • Naive approach

Singleton is a software design pattern which ensures only one object of a type is created. This is useful in when we want to create an object which manages or co ordinates some tasks in the system.

private static Singleton instance = null;
protected Singleton() {
}
public static Singleton getInstance() {
if(instance == null) {
instance = new Singleton();
}
return instance;
}
}

The call to Singleton.getInstance() will create a new Singleton type object if the varirable “instance” is null and return it, if “instance” is not null getInstance() just return the “instance”.
The variable “instnace” which is null at the startup is assigned an object at the first call to Singleton.getInstance(), subsequent call to Singleton.getInstance() return the object created at the first call.
Thus ensures only one object of Singleton is there no matter the number of time the getInstance() is called.
This works as expected in a single threaded environment, if only one thread calls getInstance(). If there are multiple threads say A and B, thread A may reach at the null check at which point thread B start executes.
At this point instance is still null to the thread A. Now thread B executes null check the instance and create a new Singleton. Then thread a again executes and create another Singleton since
instance is still null for A. So if there are multiple thread accessing the Singleton class, above code does not ensures the Singletoness.

  • Multi threaded approach.

In order to solve the problem mentioned above, we have to make sure only one thread accesses the getInstance() at a moment. The solution to ensure mutual exclusion for threads in Java is synchronizing the getInstance().

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

The above methods works and provide singletonness. However there is a performance issue. Each and every call need to execute synchronized block which slows down the execution.
In a environment where get instance() is called frequently this will cause a considerable performance degrade.

  •  Double check approach

Double check is introduced to avoid above performance hit. It Go inside synchronized block only after performing instance null check. If it is not null it won’t go inside synchronized block.

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

Double check may also cause problems due many reasons, compiler optimization is one of them. Instance = new type() seems just one operation for us. But there are multiple  operations hidden inside. They are a locating memory for the instance, creating the new object by calling the constructor, assigning the newly created object to the “instance” reference. The compiler optimization may reorder these operations depending on the compiler implementation.

Step 1) Assign object to the “instance” reference

Step 2) Constructor code
If the compiler order in above way, if another thread start executed get instance() it may see the instance as Not null (since step1 is over) but only see the default values of the attribute s of the object, not the values specified in the constructor. So the other objects get the wrong values.

  • Make instance volatile
class Singleton {
private volatile Singleton instance;
public Singleton getInstance() {
if (instance == null) {
synchronized(this) {
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}

By making the instance variable volatile above issue can be resolved since  partial values of volatile variables are not visible to other threads.

  •  A better solution with java class loading(lazy initialization)
    class Singleton {
    private static class InstanceHolder {
    public static Singleton instance = new Singleton();
    }
    
    public static Singleton getInstance() {
    return InstanceHolder.instance;
    }
    }
    

JVM guarantees a class is loaded only once. We add a inner class to store the instance. Since instance is static it is initialized at the time of class loading, thus guaranteed only one instance is created since class is loaded only once. One important thing to notice is InstanceHolder inner class is loaded only at the first call to getinstance(), so delay the instance creation until the object is needed which we call lazy initialization.

Advertisements
Comments
  1. Superb.. Explained inside out quite clearly..

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