What you may not know about Singleton Design Pattern

Most of us are familiar with the Singleton Design pattern. The intent of pattern is to “ensure a class has only one instance, and provides a global point of access to it“.

But how many of us know about possible issues which may crop-up if we don’t give a thought on how it would actually work after implementation.

Following are some of the approaches, with possible issues and solutions of each to achieve the Singleton Pattern in a neat manner.

This explanation takes C#.Net as the development environment. Wherever needed, the MSDN references have also been provided.

There are following defined Approaches to achieve the Singleton Design Pattern:

  • Singleton without lock
  • Singleton using Single-Check lock
  • Singleton using Double-Check lock
  • Singleton using Double-Check lock with volatile variable
  • Optimized Singleton managed by .Net Framework and JIT 

Singleton Design Pattern without lock

 

public sealed class BasicSingleton

{
static BasicSingleton instance=null;
BasicSingleton ()
{
}
public static BasicSingleton Instance
{
get
{
if (instance==null)
{
instance = new BasicSingleton (); // lazy initialization
}
return instance;
}
}
}

This is the most basic Singleton that you would have worked on, but the above is not thread-safe. Two different threads could both have evaluated the test if (instance==null) and found it to be true, then both create instances, which violates the singleton pattern. Let’s look at how we can improve this.

Singleton Design Pattern using Single-check lock

The most obvious next step is to introduce locking. This implementation is thread-safe. The thread takes a lock, and then checks whether or not the instance has been created before creating the instance. This ensures that only one thread will create an instance (as only one thread can be in that part of the code at a time – by the time the second thread enters it, the first thread will have created the instance, so the expression will evaluate to false).

public class LockedSingleton

{
private static LockedSingleton _instance;
private static object syncRoot = new Object();
private Singleton() {}
public static LockedSingleton Instance
{
get
{
lock(syncRoot)
{
if (_instance == null)
{
_instance = new LockedSingleton ();
}
}
return _instance;
}
}
}

But there is an issue here too. Since a lock is acquired every time an instance is requested (and let’s suppose this instance is used a lot in the application) performance starts suffering.

 Singleton Design Pattern using Double-check lock

Here, we double-check if the instance is null before entering the lock.  This improves the above approach. Only after passing the last test the member variables instantiated, and hence performance does not suffer.

public class DoubleCheckLockSingleton

{
private static Singleton _instance;
private static object syncRoot = new Object();
protected DoubleCheckLockSingleton () {}
public static DoubleCheckLockSingleton Instance
{
get
{
if (_instance == null)
{
lock(syncRoot)
{
if (_instance == null)
_instance = new DoubleCheckLockSingleton ();   //Lazy Initialization
}
}
return _instance;
}
}
}

This technique looks great at first sight but even it has its own issues. Some optimizing compilers can optimize out or reorder the lazy initialization code and reintroduce the thread safety problem in the previous examples.

Singleton Design Pattern using Double-check lock with volatile variable

A way to attempt to fix this problem could be using the volatile keyword on the member variable declaration. This should tell the compiler to not reorder the code and forgo optimization.

Please read about the volatile keyword in C# here –

http://msdn.microsoft.com/en-us/library/x13ttww7(v=vs.71).aspx

The use of volatile to make our singleton better, is as explained in the following example

public class CoolSingleton
{
private static volatile CoolSingleton _instance = null;     //use of volatile keyword
private static object syncRoot = new Object();
public static CoolSingleton Instance()
{
if (_instance == null)
{
lock (syncRoot)
{
if (_instance == null)
{
_instance = new CoolSingleton();   //Lazy Initialization
}
}
}
return _instance;
}
protected CoolSingleton() {}
}

Here we added the volatile keyword to ensure that there is no optimizer reordering of the code.

Now it looks like a Cool Singleton which is

  1. Thread-safe
  2. Has Lazy initialization
  3. Doesn’t suffer performance issues
  4. Doesn’t suffer any inadvertent complier optimization or reordering

Alternate optimized Singleton Design Pattern managed by .Net Framework and JIT

In above examples, we saw that the implementation evolved as the needs changed or we saw some issues and finally we achieved the cool singleton.

.NET provides an evolutionary step in application development. Many of the issues that had to be accounted for in the preceding examples can be addressed at the Framework level and not at the implementation level.

The following sample uses .NET, is a minimal Singleton class based loosely on the original GoF pattern, and still gets similar behavior.

public sealed class WhatASingleton

{
private WhatASingleton() {}
public static readonly WhatASingletonInstance=new WhatASingleton(); //static type initialization.
}

In this strategy, the instance is created the first time any member of the class is referenced. The common language runtime takes care of the variable initialization. The class is marked sealed to prevent derivation, which could add instances. The variable is marked readonly, which means that it can be assigned only during static initialization (which is shown here) or in a class constructor.

This implementation is similar to the preceding example, except that it relies on the common language runtime to initialize the variable. It still addresses the two basic problems that the Singleton pattern is trying to solve: global access and instantiation control. The public static property provides a global access point to the instance. Also, because the constructor is private, the Singleton class cannot be instantiated outside of the class itself; therefore, the variable refers to the only instance that can exist in the system.

Because the Singleton instance is referenced by a private static member variable, the instantiation does not occur until the class is first referenced by a call to the Instance property. This solution therefore implements a form of the lazy instantiation property

The above information is also available at http://msdn.microsoft.com/en-us/library/ee817670.aspx

What’s cool about this approach?

  1. This version is very simple and more intuitive and at the same time achieves all the goals outlined above
  2. It is a proper Singleton
  3. Has Lazy initialization: In C++, we had to do lazy initialization ourselves, to make sure the instance is created on the first call, but with the .NET Framework, this is exactly the behavior we get by default. 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 results are just like what we wanted
  4. Thread-safe initialization: The Framework addresses this too. 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, by default
  5. Does not suffer from performance issues
  6. Any compiler refactoring or optimization is not possible here

 

 

4 thoughts on “What you may not know about Singleton Design Pattern

  1. Good going. Your findings are always new and encouraging. I think you should guide freshers in IT Industry. Good goind. All the best. Pleasure to follow you.

Leave a Reply

Your email address will not be published. Required fields are marked *


seven × = 7

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>