Labels

Monday, November 15, 2010

Singleton - Creational

1.1          Introduction

There are times, when one needs to have a class, which can be only instantiated once. Singleton Design Pattern addresses to such situation by providing a design for such classes (known as Singleton class).

1.2          Description

There are at least two solutions or scenario for implementing Singleton Class. The first solution says that there should be only one shared object and reference to that object should be available only through static method like GetInstance() while making the constructor private. A number of clients can be awarded the reference to such shared object. The second solution says that the constructor should be public (as it appears in most cases) but once an object has been instantiated, an exception should be thrown for each successive constructor call; thus limiting the class to only one object.

1.3          An Example

First case Singleton can be used in a data repository or data collection where creation of more than one object can be resource wastage. Hence each client is given a reference to a single shared object to operate on. While the second case Singleton can be used in locking mechanisms. Once a client has got the object, no other client can have an object.

1.4          Class Diagram





1.5          Singleton Design pattern in C# and .NET

Approach 1: Lazy Implementation




class Singleton
  {
        private static Singleton _instance = null;
        protected Singleton() { }

        public static Singleton Instance()
        {
            if (_instance == null)
            {
                _instance = new Singleton();
            }

            return _instance;
        }
 }



This lazy initialization in the control block means that the Singleton instance is initialized, or created, only on the first call to the Instance() method. For many applications, this approach works just fine. But this method is not thread safe! Imagine two threads simultaneously checking if the instance of the class is null, when it is actually null! Both of these threads will create instance of our singleton class which is not what we want. To solve this, we use the lock keywork in C#.


Approach 2: Lock Approach

Below is the Sample code using lock.




class Singleton
    {
        protected Singleton() { }
        private static Singleton _instance = null;

        public static Singleton Instance()
        {
            if (_instance == null)
            {
                lock (typeof(Singleton))
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }



There is still some problem in the above code. Some optimizing compilers can optimize out or reorder the lazy initialization code and reintroduce the thread safety problem. To solve this .NET framework has volatile keyword. Using the volatile keyword on the member variable declaration tells the compiler to not reorder the code and forgo optimization.




class Singleton
    {
        protected Singleton() { }
        private static volatile Singleton _instance = null;

        public static Singleton Instance()
        {
            if (_instance == null)
            {
                lock (typeof(Singleton))
                {
                    if (_instance == null)
                    {
                        _instance = new Singleton();
                    }
                }
            }
            return _instance;
        }
    }



This code takes care of thread safety and compiler re-ordering issues.

Now this way of creating the singleton class is completely thread safe but what about the Performance Issues? Unfortunately, every time we want an instance of this class, we have to acquire the lock which affects the performance badly if our application is a heavily threaded application.

Lazy Initialization:

The Framework, during the JIT process, will initialize the static property when (and only when) any method uses this static property. If the property is not used, then the instance is not created. More precisely, what happens during JIT is that the class gets constructed and loaded when any static member of the class is used by any caller. In this case the result is the same.

Approach 3: Thread-safe

The Framework internally guarantees thread safety on static type initialization. In other words, in the example above, there is only one instance that would ever be created of the Singleton class.

Adding the sealed class modifier ensures that this class will not be sub-classed.

Below is a sample Singleton Usage:




class SingleTon
    {
        public int i=6;
        public static SingleTon Instance = new SingleTon(); 

     // Note: Here the non-static constructor will take precedence over static constructor.
       // So you can comment the 'Static' constructor, unless you are required to initialize any  
       // static variable before any object is created.

        static SingleTon()
        { }

        private SingleTon()
        {
            i = 7;
        }

        public static SingleTon GetInstance()
        {
            return Instance;
        }
    }


Hope this helps.

Thanks & Regards,
Arun Manglick

No comments:

Post a Comment