Tuesday, January 14, 2014

Creational DP : Singleton Design Pattern



Singleton pattern is a design pattern that restricts the instantiation of a class to one object.

This pattern involves a single class which is responsible to creates own object while making sure that only single object get created. This class provides a way to access its only object which can be accessed directly without need to instantiate the object of the class

There are different ways /approaches to achieve singleton design pattern
 

1)      Eager initialization: This is a design pattern where an instance of a class is created much before it is actually required. Mostly it is done on system start up. In singleton pattern, it refers to create the singleton instance irrespective of whether any other class actually asked for its instance or not.

public class Singleton {

    private static final Singleton INSTANCE = new Singleton();

    private Singleton() {}

    public static Singleton getInstance() {

        return INSTANCE;

    }

}

Instance is created irrespective of it is required in runtime or not. If this instance is not big object and you can live with it being unused, this is best approach.

This method has a number of advantages:
  • The instance is not constructed until the class is used.
  • There is no need to synchronize the getInstance() method, meaning all threads will see the same instance and no (expensive) locking is required.
  • The final keyword means that the instance cannot be redefined, ensuring that one (and only one) instance ever exis
 
2)            Lazy Initialization: It is the tactic of delaying the creation of an object, the calculation of a value, or some other expensive process until the first time it is needed. In singleton pattern, it restricts the creation of instance until requested first time

// Correct but possibly expensive multithreaded version
class Foo {
    private Helper helper;
    public synchronized Helper getHelper() {
        if (helper == null) {
            helper = new Helper();
        }
        return helper;
    }
    // other functions and members...
}


On first invocation, above method will check if instance is already created using instance variable. If there is no instance i.e. instance is null, it will create an instance and will return its reference. If instance is already created, it will simply return the reference of instance.But, this method also has its own drawbacks. Lets see how. Suppose there are two    threads T1 and T2. Both comes to create instance and execute “instance==null”, now both threads have identified instance variable to null thus assume they must create an instance. They sequentially goes to synchronized block and create the instances. At the end, we have two instances in our application.
This error can be solved using double-checked locking. This principle tells us to recheck the instance variable again in synchronized block in given below way:


 
// Broken multithreaded version
// "Double-Checked Locking" idiom
class MyClass {
    private MyHelper helper;
    public MyHelper getHelper() {
        if (helper == null) {
            synchronized(this) {
                if (helper == null) {
                    helper = new MyHelper();
                }
            }
        }
        return helper;
    }


3) Static Initialization : If you have little idea about class loading sequence, you can connect to the fact that static blocks are executed during the loading of class and even before the constructor is called. We can use this feature in our singleton pattern also like this:



public class StaticBlockSingleton {
  private static final StaticBlockSingleton INSTANCE;
 
  static {
         try {
                 INSTANCE = new StaticBlockSingleton();
         } catch (Exception e) {
                 throw new RuntimeException(" Error!", e);
         }
  }
 
  public static StaticBlockSingleton getInstance() {
         return INSTANCE;
  }
 
  private StaticBlockSingleton() {
                   // ...
     }
}


Above code has one drawback. Suppose there are 5 static fields in class and application code needs to access only 2 or 3, for which instance creation is not required at all. So, if we use this static initialization. we will have one instance created though we require it or not.
  


4)    The solution of Bill Pugh :  Researcher Bill write the code Pugh's efforts on the "Double-checked locking" idiom led to changes in the Java memory model in Java 5 and to what is generally regarded as the standard method to implement Singletons in Java. The technique known as the initialization on demand holder idiom, is as lazy as possible, and works in all known versions of Java. It takes advantage of language guarantees about class initialization, and will therefore work correctly in all Java-compliant compilers and virtual machines.
The nested class is referenced no earlier (and therefore loaded no earlier by the class loader) than the moment that getInstance() is called. Thus, this solution is thread-safe without requiring special language constructs (i.e. volatile or synchronized).

   

public class Singleton {
        
        private Singleton() { }
        /**
        * SingletonHolder is loaded on the first execution of Singleton.getInstance()
        * or the first access to SingletonHolder.INSTANCE, not before.
        */
        private static class SingletonHolder {
                public static final Singleton INSTANCE = new Singleton();
        }
        public static Singleton getInstance() {
                return SingletonHolder.INSTANCE;
        }
}

 

5)     Using Enum : This type of implementation recommend the use of enum. Enum, as written in java docs, provide implicit support for thread safety and only one instance is guaranteed. This is also a good way to have singleton with minimum effort.  
 
public enum Singleton {
        INSTANCE;
        public void execute (String arg) {     
            // perform operation here
        }
}

This approach implements the singleton by taking advantage of Java's guarantee that any enum value is instantiated only once in a Java program. Since Java enum values are globally accessible, so is the singleton, initialized lazily by the classloader. The drawback is that the enum type is somewhat inflexible.
6)    readResolve() Method :   If the Singleton class implements the 
   java.io.Serializable interface, when a singleton   is serialized and then deserialized more than once, there will be multiple instances of Singleton created. In order to avoid this the readResolve method should be implemented

public class Singleton implements Serializable {

               // This method is called immediately after an 
               //object of this class is deserialized.

               // This method returns the singleton instance.

               protected Object readResolve() {

                       return getInstance();

               }

        }
 

Let’s say your application is distributed and it frequently serialize the objects in file system, only to read them later when required. Please note that, de-serialization always creates a new instance. 
 
Lets understand using an example

Our singleton class is:



public class DemoSingleton implements Serializable {

        private volatile static DemoSingleton instance = null;
 
        public static DemoSingleton getInstance() {
               if (instance == null) {
                       instance = new DemoSingleton();
               }
               return instance;
        }
 
        private int i = 10;
 
        public int getI() {
               return i;
        }
 
        public void setI(int i) {
               this.i = i;
        }
}
It will give output as below
20
10

 

To solve this issue, we need to include readResolve() method in our DemoSingleton class. This method will be invoked when you will de-serialize the object. Inside this method, you must return the existing instance to ensure single instance application wide. 

Intuitively,this algorithm seems like an efficient solution to the problem. However, this technique has many subtle problems and should usually be avoided. For example, consider the following sequence of events:


public class DemoSingleton implements Serializable {

        private volatile static DemoSingleton instance = null;

        public static DemoSingleton getInstance() {

               if (instance == null) {
                       instance = new DemoSingleton();
               }
               return instance;
        }


        protected Object readResolve() {
               return instance;
        }

        private int i = 10;

        public int getI() {
               return i;
        }


        public void setI(int i) {
              this.i = i;

        }
}

It will give output as below

20
20 
Notes about double-checked locking : 

It is typically used to reduce locking overhead when implementing "lazy initialization" in a multi-threaded environment,

1)      Thread A notices that the value is not initialized, so it obtains the lock and begins to initialize the value.


2)      Due to the semantics of some programming languages, the code generated by the compiler is allowed to update the shared variable to point to a partially constructed object before A has finished performing the initialization. For example, in Java if a call to a constructor has been inlined then the shared variable may immediately be updated once the storage has been allocated but before the inlined constructor initializes the object


3)      Thread B notices that the shared variable has been initialized (or so it appears), and returns its value. Because thread B believes the value is already initialized, it does not acquire the lock. If B uses the object before all of the initialization done by A is seen by B (either because A has not finished initializing it or because some of the initialized values in the object have not yet percolated to the memory B uses (cache coherence)), the program will likely crash.


One of the dangers of using double-checked locking in J2SE 1.4 (and earlier versions) is
that it will often appear to work: it is not easy to distinguish between a
correct implementation of the technique and one that has
subtle problems .
 
 

   As of J2SE 5.0, this problem has been fixed. The volatile keyword now ensures that multiple threads handle the singleton instance correctly // Works with acquire/release semantics for volatile // Broken under Java 1.4 and earlier semantics for volatile class 

Foo {
    private volatile Helper helper;
    public Helper getHelper() {
        Helper result = helper;
        if (result == null) {
            synchronized(this) {
                result = helper;
                if (result == null) {
                    helper = result = new Helper();
                }
            }
        }
        return result;
    }

 }

Note the local variable result, which seems unnecessary. This ensures that in cases where helper is already initialized (i.e., most of the time), the volatile field is only accessed once, which can improve the method's overall performance by as much as 25 percent
 
// Correct lazy initialization in Java
@ThreadSafe
class Foo {
    private static class HelperHolder {
       public static Helper helper = new Helper();
    }
 
    public static Helper getHelper() {
        return HelperHolder.helper;
    }
}

This relies on the fact that inner classes are not loaded until they are referenced. Semantics of final field in Java 5 can be employed to safely publish the helper object without using volatile


public class FinalWrapper<T> {
    public final T value;
    public FinalWrapper(T value) {
        this.value = value;
    }
}
 
public class Foo {
   private FinalWrapper<Helper> helperWrapper;
 
   public Helper getHelper() {
      FinalWrapper<Helper> wrapper = helperWrapper;
 
      if (wrapper == null) {
          synchronized(this) {
              if (helperWrapper == null) {
                  helperWrapper = new FinalWrapper<Helper>(new Helper());
              }
              wrapper = helperWrapper;
          }
      }
      return wrapper.value;
   }
} 
 

The local variable wrapper is required for correctness. Performance of this implementation is not necessarily
better than the volatile implementation.



No comments: