Sunday, 24 March 2013

Singleton Design pattern

Singleton Design patterns is the most simple of all the design patterns in Java. It is also the most frequently asked interview question. So lets go ahead and understand what this design pattern is all about.


Understanding Singleton Design pattern

              Singleton as the name suggests there can be only one instance of the class.There are various cases in which we strictly need only one instance of the class. Like for example we Window manager or Print spoolers or filesystems.  There are only two main points in the definition of Singleton Design pattern - 

  1. There must be only instance allowed for the class.
  2. This single instance of the class must be allowed global point of access.
For better understanding see the following class diagram -

 

Singleton instance creation

         Lets see the code first and then we will try to understand it.


package designPatterns;

public class SingletonPatternDemo {

    private static volatile SingletonPatternDemo singleInstance;

    private SingletonPatternDemo() {
    } // Constructor

    public static SingletonPatternDemo getSingleInstance() {
        if (singleInstance == null) {
            synchronized (SingletonPatternDemo.class) {
                if (singleInstance == null) {
                    singleInstance = new SingletonPatternDemo();
                }
            }

        }
        return singleInstance;
    }
}

     Lets understand the code written above. First of all we have the package and the class declaration. Carefully analyze the next line  private static SingletonPatternDemo singleInstance; we have a reference to the object of class SingletonPatternDemo. Note that it is just the reference and we have not created any associated object yet. Another view point can be that we have not yet used any space on heap for any object. This reference is defined as private and static. It is private which mean we cannot directly access it using class objects For Ex. objectName.singleInstance is not allowed. See Access modifiers for more details. Next it is also defined to be static which means the variable belongs to the class and not individual objects. We will get to static keyword in subsequent tutorials but for now you understand it this way - we can access the variable using SingletonPatternDemo.singleInstance i.e className.instanceVariableName. Next we have defined our constructor to be private which means we cannot create any objects by using the new keyword. Only way to create a object is the getSingleInstance() function which is public and static and returns an object of SingletonPatternDemo class. Again static means we can access it using the class Ex. SingletonPatternDemo.getSingleInstance().

         Inside the getSingleInstance() method we first check whether instance of the class is already created. If it is already created we return the same instance of the class(as we are allowed to have only one instance of the class) but if there is no instance of the class that is already created we create one and return it.What we have inside the getSingleInstance() method is what we call a Double locking mechanism which i will 
explain explicitly.But before that lets understand what synchronized is.

Note : 

Also note that the  singleton instance is defined to be volatile. This keyword is used for consistency of data across threads. You know that each thread has it's cache where the data reference by the thread is cached and when a thread modifies the data it is still in it's local cache and may not be visible to other threads. To avoid this problem variables can be declared volatile. By declaring a variable as volatile we essentially instruct JVM not to cache the variable in threads cache. Instead all the reads and writes must directly happen in the main memory.

Understanding synchronized keyword

          This keyword is used when we are dealing with multi-threading. Note that only member functions can be defined as  synchronized not the member variables or class itself. When we declare a function to be synchronized it means only one thread can access it at a given point of time. Other than synchronized functions we can have synchronized blocks like the one we have used in the above code. It also means the same - only one thread can access the block at a given point of time. We will cover this in depth when we go through what do we mean by a class being thread-safe and related advanced topics but till then given information should suffice.Next lets understand what is the Double locking mechanism we talked about.

Understanding Double locking mechanism

     Lets see the above code again


if (singleInstance == null) {
            synchronized (SingletonPatternDemo.class) {
                if (singleInstance == null) {
                    singleInstance = new SingletonPatternDemo();
                }
            }

This is double locking mechanism. Lets see how this works. Now our aim was to allow only single instance of the class. In multi-threading scenario lets say one thread checks  singleInstance finds it to be null and enters the synchronized block. Lets say now there is s context switch or time quantum of the process is over. Next thread takes over, checks if singleInstance is null which is true so even this thread will enter the first if block. Now if we did not have the second check in the synchronized block both thread would go ahead and create an instance of the class. Final result would be we having two instances of our class which is against our Singleton goal. Hence we do a double check once again in the synchronized block. Now since it is in synchronized block only one thread will execute it at a given time and create a instance. When second thread enters this block it will find singleInstance is not null and will not create a new instance. This method is what we call double locking mechanism.

Early and lazy instantiation in singleton pattern

       What we did in above code example is  lazy instantiation which means we create instance of the class only when it is needed. On the other hand we have Early instantiation which means we create the instance once as soon as the class is loaded and return the same when user need it. Code for  Early instantiation is as follows - 


package designPatterns;

public class SingletonPatternDemo {

    private static SingletonPatternDemo singleInstance  = new
 SingletonPatternDemo() ;

    private SingletonPatternDemo() {
    } // Constructor

    public static SingletonPatternDemo getSingleInstance() {
        return singleInstance;
    }
}

  So we create instance of the class as soon as class is loaded and just return it when getSingleInstance() is called. This demonstrates Early instantiation.




Note : 


You must have notice there is no synchronization involved in early initialization. Since Singleton instance is static variable it initialized when class is first loaded into memory so creation of instance is inherently thread-safe.


Eclipse Snapshot

 


Note : In Java you must have used Runtime class quite some time. For example to execute processes from Java - Runtime.getRuntime().exec(). This Runtime class is a Singleton class. There is only one instance of this class per JVM.



yes as you must have notice it, they have use Early initialization ( not lazy init).

Is Singleton instance garbage collected?

Simple plain answer is No!

This was an issue prior to Java 1.2 in which if singleton instance did not have a global reference it would be garbage collected. This defeated the very purpose of singleton as next reference created a new instance of it. But this was fixed in Java 1.2.

New garbage collection model forbids any of the classes that it has loaded from being garbage collected unless all the classes are unreferenced (in which case the class loaded is itself eligible for GC). So unless the class loader is garbage collected the singleton class having static reference to singleton instance is never eligible for garbage collection. So you can be sure that the singleton instance will never be GCed.


When Singleton does not remain Singleton?

There are various ways Singleton property can be violated
  1. Use reflection to create new instance
  2. Deserialize and Serialize it again
  3. Clone it if it implements Cloneable interface.
  4. Use different class loaders etc.
Prevention :
  1. Create constructor and throw exception from it
  2. Implement Serializable and return same instance in readResolve() method
  3. throw exception from clone method
But the best way to avoid these is to design singleton object using enum : The final clone method in Enum ensures that enum constants can never be cloned, and the special treatment by the serialization mechanism ensures that duplicate instances are never created as a result of deserialization. Reflective instantiation of enum types is prohibited. Together, these four things ensure that no instances of an enum type exist beyond those defined by the enum constants.

Related Links


No comments:

Post a Comment

t> UA-39527780-1 back to top