Proper implementation of Singleton pattern

Singleton pattern is one of the most essential patterns when it is applied correctly. There are some paramount tips and trick to be considered to get maximum efficiency of this pattern. This post will be all about implementing singleton pattern properly to avoid its misapplications.

When should I implement it?

The #1 reason to implement Singleton pattern is the need to restrict multiple instantiation of a class to at most one single instance. If you don’t need to keep at most one instance of a class, then you should consider the classical way of class implementations, i.e. either static of non-static, to keep the design simple to maintain.

The #2 additional reason is the need for thread safety of single instance method.  Otherwise, it may be also wise to implement a conventional static method without singleton pattern.

Note: Most of the time, the first reason is considered to be sufficient to implement singleton pattern and the second reason is missed by an oversight.

How to implement it?

The implementation below will be subdivided into two steps addressing the 2 abovementioned primary need stepwise.

Need #1: Keeping at most one single instance

The code below is simple version of singleton pattern to address the first need above. So, the  implementation will allow us to keep at most one single the instance of our class.  

using System;

public class ProperSingleton1
{
    private static ProperSingleton1 _instance;

    public ProperSingleton1 Instance
    {
        get
        {
            if(_instance == null)
            _instance = new ProperSingleton1();

            return _instance;
        }
    }

    public void TargetMethod()
    {
        Console.WriteLine ("Target method executed");
    }
}
This implementation will run with no problem unless there is no more than one thread calling the TargetMethod.  The existence of no more than single client of TargetMethod will prevent race conditions.  If there are concurrent threads calling TargetMethod, the class must be tweaked to address thread safety issues as shown in the second step below.
 

Note: The class itself can also be defined as static, i.e. public static class ProperSingleton1.  However, if the class is defined as static then all properties and methods in the class also must have been declared as static.

Need #2: Thread safety and handling concurrency issues

What if the following race condition occured:  Thread A is switched when it is just about to initialize the variable _instance, and Thread B initialized until it is switched.  So when ot comes to Thread A again, the _instance will be instantiated again, which violates the primary reason to use Singleton pattern.
 
The solution for this race condition is implementing double-checked lock as follows.
using System;

public class ProperSingleton2
{
    private static ProperSingleton2 _instance;

    private double _someField = 0.0;
    private static readonly object _mutexObj = new object();

    public ProperSingleton2 Instance
    {
        get
        {
            if(_instance == null)//first check 
            {
                lock(_mutexObj) // lock
                {
                    if(_instance == null) // second check
                        _instance = new ProperSingleton2();
                }
            }

            return _instance;
        }
    }

    public void TargetMethod()
    {
        Console.WriteLine ("Target method executed");
    }
}
This implementation will prevent unintended second instantiation of class.  However, this is not the proper way of implementation addressing the need for thread safety, yet.  There is one more subtle but critical issue to consider.  It is volatile keyword.
 
The problem, now, is that the write/read operations is not sequentially consistent.  The compiler may perform some unintended optimisations.  For example, instantiation of a class may be considered to compromise two basic steps such as instantiation of fields and instantiation of class reference.  As an optimization, the class reference may be initialized first, before the initialization of the fields of the class.  And these two steps are not atomic.  So,
  • Thread A, has just initialized the _instance variable and is about to initialize the fields of class, 
  • Thread B may have read the non-null reference of the _instance variable (since it is located in shared memory location by definition of static) and conclude that the _instance variable has already been intialized completely. The second thread will fail when it happens to access the fields of _instance before they are actually initialized. 
This problem is resolved by defining _instance variable as volatile as follows.  Now, the compiler will guarantee the order of read/write operations as expected by means of inserting some memory barriers.  You can find more information here about the details of memory barriers.
using System;

public class ProperSingleton3
{
    private static volatile ProperSingleton3 _instance;

    private double _someField = 0.0;
    private static readonly object _mutexObj = new object();

    
    public ProperSingleton3 Instance
    {
        get
        {
            if(_instance == null)//first check 
            {
                lock(_mutexObj) // lock
                {
                    if(_instance == null) // second check
                        _instance = new ProperSingleton3();
                }
            }

            return _instance;
        }
    }

    public void TargetMethod()
    {    
        Console.WriteLine ("Target method executed");
    }
}

More optimization

Checking the volatile variable is more expensive than checking local variable namely tmpInstance.  So we can assign the value of volatile variable _instance to a local variable tmpInstance and perform the necessary checks on the local variable.  As a consequence, Joshua Bloch claims that there is %25 improvement on performance of his Java implementation on his book “Effective Java, Second Edition”.
using System;

public class ProperSingleton4
{
    private static volatile ProperSingleton4 _instance;
    private double _someField = 0.0;
    private static readonly object _mutexObj = new object();
    public ProperSingleton4 Instance
    {
        get
        {
            ProperSingleton4 tmpInstance = _instance;

            if(tmpInstance == null)//first check 
            {
                lock(_mutexObj) // lock
                {
                    tmpInstance = _instance;

                    if(tmpInstance == null) // second check
                    {
                        _instance = new ProperSingleton3();
                        tmpInstance = _instance;
                    }
                }
            }
            return tmpInstance;
        }
    }
    public void TargetMethod()
    {
        Console.WriteLine ("Target method executed");
    }
}


.net Tips

When implementing double checked lock the volatile keyword is necessary before .net 2.0 but unnecessary in .net 2.0 and later.  In .net 4.0 and later, the generic class Lazy is also another option to use since it implements double-checked lock internally. 

    using System;
    public class ProperSingleton5
    {
        private static readonly Lazy _instance = 
             new Lazy(() => new ProperSingleton5());
        private double _someField = 0.0;
        public ProperSingleton5 Instance 
        { 
            get 
            { 
                return _instance.Value; 
            } 
        } 
        
        public void TargetMethod() 
        { 
            Console.WriteLine("Target method executed"); 
        }
    }

Further references

  1. Double-checked locking | Wikipedia
  2. Memory Model, Memory Barrier and Singleton Pattern in .NET
  3. Understand the Impact of Low-Lock Techniques in Multithreaded Apps
  4. Effective Java (2nd Edition)