The Singleton Pattern – Design Patterns II.

The Singleton pattern is one of the most well-known and probably the most often used design pattern. It is used to enforce that only a single instance of a class can be instantiated within an application (To be more precise within an AppDomain. For more details please see remarks at the bottom). The key of this pattern’s success is its well focused object and easy implementation.Despite all the merits there are a lot of misunderstanding around the proper implementation and usage of the Singleton pattern.

First of all it is a code smell to use the singleton pattern extensively since it introduces a kind of global memory. When used for instrumentation it is fine. However my experience shows that in a lot of cases too much business logic is put into this structure needlessly going against design principles. Here is a nice description about the deficiencies of the Singleton pattern.

The simplest implementation of the singleton pattern is shown in Example 1. The instance of the class is stored within a static field and is instantiated in the field initializer. If the construction of the instance is more complex then a static constructor can be used. Usually this solution works perfectly and easy to implement and understand.

Example 1:

   public class Singleton
   {
      private static Singleton _instance = new Singleton();
      
      public static Singleton Instance
      {
         get { return _instance; }
      }
      
      private Singleton()
      {
         Console.WriteLine("Singleton created");
      }
   }

The reason many refuse this simple implementation is the lack of lazy initialization. The basic idea is to instantiate the singleton class only on demand to save memory and gain more control over the life-cycle of the singleton. But if an application always instantiates the Singleton then there is little use of lazy initialization in terms of memory usage. Often there is neither real need for the life-cycle control.

When lazy initialization is beneficial double checked locking can server as a simple but efficient solution. The first check is to avoid any locking if the singleton is already created. The following lock statement ensures that only single thread can enter the critical section of object creation at a time. Since multiple concurrent threads can be blocked by this lock a second check is needed within the critical section to avoid the recreation of the singleton. Note that to support multi-thread environment the volatile keyword must be used. The implementation of double checked locking is shown in Example 2.

Example 2:

 
   public class Singleton
   {
      private static object _instanceLock = new Object();
      private static volatile Singleton _instance;
      
      public static Singleton Instance
      {
         get
         {
            if (_instance == null)
            {
               lock(_instanceLock)
               {
                  if (_instance == null)
                  {
                     _instance = new Singleton();
                  }
               }
            }
            return _instance;
         }
      }
      
      private Singleton() { Console.WriteLine("Singleton created"); }
   }

There is a more elegant solution that omits any explicit locking. The C# 4.0 language specification (10.12) says

The static constructor for a closed class type executes at most once in a given application domain. The execution of a static constructor is triggered by the first of the following events to occur within an application domain:

  • An instance of the class type is created.
  • Any of the static members of the class type are referenced.

Buildt upon the fact that the body of the static constructor executes at most once locking becomes avoidable. In Example 3 a private inner class is introduced with a single static field that holds the singleton instance and a static constructor that initializes it. According to the specification the instance is instantiated when the Instance property accessor of the Singleton class gets called. And this is exactly how lazy initialization must work.

Example 3:

public class Singleton
{
   public static Singleton Instance
   {
      get { return _InstanceContainer.Item; }
   }
   
   private class _InstanceContainer
   {
      public static readonly Singleton Item;
      static _InstanceContainer()
      {
         Item = new Singleton();
      }
   }
   
   private Singleton()
   {
      Console.WriteLine("Singleton created");
   }
}

As mentioned in the introduction the scope of static items is AppDomain. But this can be overriden. If a field is decorated with the attribute ThreadStatic then the scope narrows to thread level. That is, every single thread in the AppDomain will have its own instance of the static field.