Singleton Pattern

The singleton pattern falls into Creational patterns.

When it is used

  • Used when we want only one object to be shared between clients.
  • The client should not create an object.
  • The object should be created only once and then the same object should service all the client requests.

How to Implement

There are various different ways of implementing the singleton pattern in C# based on thread safety, lazy-initialization and performance. But all these implementations share some common characteristics:

  • A single constructor, which is private and parameter-less. This prevents other classes from instantiating it. It also prevents sub-classing – if a singleton can be sub-classed and if each of those subclasses can create an instance, the pattern is violated.
  • The class is sealed, though this is optional/unnecessary, but may help the JIT to optimize things more.
  • A static variable which holds a reference to the single created instance.
  • A public static means of getting the reference to the single created instance, creating one if necessary.
Singleton implementation without thread safety

public sealed class SingletonImplementation
{
//static variable which holds the single instance at any given time
private static SingletonImplementationtheInstance;

//constructor is private so we cannot create instance of the class directly
private SingletonImplementation()
{
}

//static method used to create and return the instance of the class
public static SingletonImplementationGetInstance()
{
if(theInstance == null)
{
theInstance = new SingletonImplementation();
}
return theInstance;
}
}

The above code is a bad implementation as it’s not thread-safe and we should avoid it. 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. Note that in fact the instance may already have been created before the expression is evaluated, but the memory model doesn’t guarantee that the new value of instance will be seen by other threads unless suitable memory barriers have been passed.

Singleton implementation with thread safety

public class SingletonImplementation
{
//static variable which holds the single instance at any given time
private static SingletonImplementationtheInstance;

//constructor is private so we cannot create instance of the class directly
private SingletonImplementation()
{
}

//static method used to create and return the instance of the class
public static SingletonImplementationGetInstance()
{
lock(typeof(SingletonImplementation))
{
if(theInstance == null)
{
theInstance = new SingletonImplementation();
}
returntheInstance;
}
}
}

The thread takes out a lock on a shared object, and then checks whether or not the instance has been created before creating the instance. This takes care of the memory barrier issue (as locking makes sure that all reads occur logically after the lock acquire, and unlocking makes sure that all writes occur logically before the lock release) and ensures that only one thread will create an instance. Unfortunately, performance suffers as a lock is acquired every time the instance is requested.

Singleton implementation with thread safety without using locks- not quite as lazy

public class SingletonImplementation
{
//static variable which holds the single instance at any given time
private static readonly SingletonImplementationtheInstance = new                                                                                                                      SingletonImplementation();

//constructor is private so we cannot create instance of the class directly
private SingletonImplementation()
{
}

// Explicit static constructor to tell C# compiler not to mark type as beforefieldinit
static SingletonImplementation()
{
}

//static method used to create and return the instance of the class
public static SingletonImplementation GetInstance()
{
return theInstance;
}
}

As you can see, this is really is extremely simple – but why is it thread-safe and how lazy is it? Well, static constructors in C# are specified to execute only when an instance of the class is created or a static member is referenced, and to execute only once per AppDomain. Given that this check for the type being newly constructed needs to be executed whatever else happens, it will be faster than adding extra checking as in the previous examples. There are a couple of wrinkles, however:

  • It’s not as lazy as the other implementations. In particular, if you have static members other than Instance, the first reference to those members will involve creating the instance.
  • There are complications if one static constructor invokes another which invokes the first again.
  • The laziness of type initializers is only guaranteed by .NET when the type isn’t marked with a special flag called beforefieldinit. Unfortunately, the C# compiler marks all types which don’t have a static constructor (i.e. a block which looks like a constructor but is marked static) as beforefieldinit. It also affects performance.
Singleton implementation with thread safety without using locks- fully lazy instantiation

public class SingletonImplementation
{
//constructor is private so we cannot create instance of the class directly
privateSingletonImplementation()
{
}

public static SingletonImplementation theInstance { get { return Nested.instance; } }

private class Nested
{
// Explicit static constructor to tell C# compiler not to mark type as beforefieldinit                             static Nested()
{
}
internal static readonly SingletonImplementation                                                                         theInstance = new SingletonImplementation ();
}
}

Here, instantiation is triggered by the first reference to the static member of the nested class, which only occurs in Instance. This means the implementation is fully lazy, but has all the performance benefits of the previous ones. Note that although nested classes have access to the enclosing class’s private members, the reverse is not true, hence the need for instance to be internal here. That doesn’t raise any other problems, though, as the class itself is private. Though the code is a bit more complicated in order to make the instantiation lazy.

Singleton implementation with thread safety without using locks- using .NET 4’s Lazy type

If you’re using .NET 4 (or higher), you can use the System.Lazytype to make the laziness really simple. All you need to do is pass a delegate to the constructor which calls the Singleton constructor – which is done most easily with a lambda expression.

public class SingletonImplementation
{
//static variable which holds the single instance at any given time
private static readonly Lazy< SingletonImplementation > lazy =
new Lazy< SingletonImplementation >(() => new SingletonImplementation ());

//constructor is private so we cannot create instance of the class directly
privateSingletonImplementation()
{
}

//static method used to create and return the instance of the class
public static SingletonImplementationGetInstance()
{
returnlazy.Value;
}

public int Addition(int i, int j)
{
returni+j;
}

}

It’s simple and performs well. It also allows you to check whether or not the instance has been created yet with the IsValueCreated property if you need that.

Performance vs laziness

In many cases, there won’t be any actual requirement of full laziness – unless your class initialization does something particularly time-consuming, or has some side-effect elsewhere, it’s probably fine to leave out the explicit static constructor shown above. This can increase performance as it allows the JIT compiler to make a single check (for instance at the start of a method) to ensure that the type has been initialized, and then assume it from then on. If your singleton instance is referenced within a relatively tight loop, this can make a (relatively) significant performance difference. You should decide whether or not fully lazy instantiation is required, and document this decision appropriately within the class.

Implementation of locking is good practice and give us thread safety but it comes with the cost of performance.

0 Comments

Leave a Comment