Monday, November 7, 2011

What is Singleton and how is it implemented?

I was getting a walk through of the basics of C# when came across this good article on Singleton design pattern. Sharing few concepts which can be used during interviews or for implementations.


Singleton can be implemented in various ways, here are some of the options with their tradeoff from MSDN.
using System;

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
}

This implementation has two main advantages:
·  Because the instance is created inside the Instance property method, the class can exercise additional functionality (for example, instantiating a subclass), even though it may introduce unwelcome dependencies.
·  The instantiation is not performed until an object asks for an instance; this approach is referred to as lazy instantiation. Lazy instantiation avoids instantiating unnecessary singletons when the application starts.
The main disadvantage of this implementation, however, is that it is not safe for multithreaded environments. If separate threads of execution enter the Instance property method at the same time, more that one instance of the Singleton object may be created. Each thread could execute the following statement and decide that a new instance has to be created:
 
if (instance == null)

To overcome the above error here is one more solution:
public sealed class Singleton
{
   private static readonly Singleton instance = new Singleton();
   
   private Singleton(){}
 
   public static Singleton Instance
   {
      get 
      {
         return instance; 
      }
   }
}

The only potential downside of this approach is that you have less control over the mechanics of the instantiation.
MultiThreaded Instantiation:
Static initialization is suitable for most situations. When your application must delay the instantiation, use a non-default constructor or perform other tasks before the instantiation, and work in a multithreaded environment, you need a different solution.
using System;
 
public sealed class Singleton
{
   private static volatile Singleton instance;
   private static object syncRoot = new Object();
 
   private Singleton() {}
 
   public static Singleton Instance
   {
      get 
      {
         if (instance == null) 
         {
            lock (syncRoot) 
            {
               if (instance == null) 
                  instance = new Singleton();
            }
         }
 
         return instance;
      }
   }
}
the variable is declared to be volatile to ensure that assignment to the instance variable completes before the instance variable can be accessed.L
Lastly, this approach uses a syncRoot instance to lock on, rather than locking on the type itself, to avoid deadlocks. 

No comments: