One of the biggest advantages of OOP is the ability to have multiple instances of the same object. This lets your object oriented code handle multiple customers, multiple acccounts, multiple whathaveyou without doing anything special (the runtime of your platform will handle the creation and destruction of these instances for you). Great!

What if the multiple instances were actually a nuisance for your particular scenario? What if you wanted just ONE instance – and no more. All your clients would use this same common instance. How do you suppress (or work around) your runtime’s natural inclination to create multiple instances for you?

This scenario is more common than one might imagine. In real life, say you are modeling a company with employees. The company is common to all the employees. It can be modeled as a single instance – as opposed to an Employee – which can be modeled as an instance class. The same reasoning can be applied when one needs to model a bank with customers (bank=single instance, customer=multiple instances). A single instance is modeled using the Singleton Pattern in C#. The Singleton pattern is one of the most widely used in object oriented programming. The basic idea is to prevent multiple instances of a class. Before we get to the Singleton itself, one might ask – how does this differ from a static class?

Difference between a Static class and a Singleton

Static classes are used whenever there is no reason to associate an identity with an object. For example – if one were modeling a Financial Application, a class representing Money (containing numeric conversion methods etc.) could be designed as static. There is no really good reason to pass instances of the Money class around. All one needs is one single object representing Money and it is not tied to an identity (there isn’t a Money1 and a Money2 for two different end users). However – an object representing the Account for the same two users – does require an identity. Each account would need to be tied to a unique user – hence we would need independent instances of the Account object.  Static would not be a good choice for the Account class.

There are several other differences between static classes and regular instantiable classes. One of the other driving factors is whether we need to determine something at runtime. Say – our object – on loading up – needed to determine the type of the operating system (OSType). A static class needs to know everything at compile time – so it would not be a good choice for this runtime need of ours. A good overview of some of the reasons to use a static class can be found on MSDN.

It also helps to remember that a static class is never actually instantiated.

While we have discussed when to use a static class versus instances, we haven’t yet discussed when to use singletons versus static classes.

There is one school of thought that says – never use a singleton – and another that says – avoid static classes altogether. Personally, I belong to the latter school of thought.

Here are a few reasons I believe that static classes can be replaced with equivalent Singletons:

  1. Multiple Instances; In case you want more than one instance down the road. With a Singleton, you always retain the flexibility of modifying the class to (to create more than one instance) later – without affecting any consumers of the class. With a static class, you can do the same thing but only at the cost of breaking (modifying) all consumers.
  2. Initialization: A static class is always initialized right away (at compile time). There is no flexibility in when or how it is to be initialized (there is a static constructor in c# – but it is nothing more than a compile time initialization method). With a Singleton, you have control over when to initialize it. Using lazy Ioading, a singleton can be initialized only when it is needed.
  3. State: Holding state – If you need a centralized place to hold stateful information (for e.g. a Visitor Count Tracker on your website), a Singleton is a good choice.

We have discussed some of the reasons why an instance class (implemented as a single instance i.e. a Singleton) offers more power and flexibility than a Static class. More generally, the difference between static classes based programs and instances (objects) based applications lies at the heart of the difference between procedural programming and Object Oriented programming.

So – we have concluded that we do need an identity based class, which is capable of holding state and which can be possibly modified down the road to return more than one instance. For now though, we are only interested in a single instance. On to the Singleton pattern.

The Singleton Pattern

The code below demonstrates the basic Singleton pattern.

Code Discussion

  1. Line 3: Static field to hold the singleton: Since we need to create the singleton one time only, we use a static field to hold it (notice that this is different from using a static class – all we are doing is having a static field inside a regular class).
  2. Note also that there is no constructor – since no one is allowed to create instances of this class.
  3. Line 6: The Singleton class does a simple check on itself to see if it exists (pretty existential if you ask me). If it doesn’t, it creates itself this one time only – so that it will always find itself in future checks.
Code Snippet
  1. public class Singleton
  2. {
  3.   public static Singleton Instance  = null;
  4.   public static Singleton CreateInstance()
  5.   {
  6.     if(Instance == null)
  7.       Instance = new Singleton();
  8.      return Instance;
  9.    }
  10. }

What can go wrong?

Concurrent Access: The first potential problem is the same problem that affects multiple contention of a single resource – concurrency. You may wonder how it affects this simple class with barely 8 lines of code.

Consider thread1 and thread2 calling the method CreateInstance().

Consider thread1 on line 6 has just finished checking if instance is null. It sees instance as null. Before it can create the new Singleton, it gets pre-empted by a clock tick. Now thread2 comes along and goes through the entire method – including the Instance = new Singleton(). So far all looks good. Until Thread1 returns. Remember that Thread1  still thinks that instance is null since that was the last thing it executed. So – it goes ahead and creates yet another instance ! All of a sudden, our simple class that only wanted to create itself once – has found itself created twice!

This is a common problem in multi-threaded applications and there are several simple workarounds for it. The most common one involves locking. Locking a resource is equivalent to saying that whenever we have multiple consumers vying for that resource, we are going to put them all in a line (serialize them). It effectively serializes simultaneous (parallel) requests.

Workaround 1 –  Use a Lock

Code Snippet
  1. public class SingletonWithLocking
  2.     {
  3.         static object locker = new object();
  4.         public static Singleton Instance  = null;
  5.         public static Singleton CreateInstance()
  6.         {
  7.           lock (locker)
  8.           {
  9.               if (Instance == null)
  10.                   Instance = new Singleton();
  11.           }
  12.          return Instance;
  13.         }
  14.     }

 

Code Discussion

  1. Line 3: Declare a simple object called locker. This will act as the lock on the lines of code that are sensitive to concurrent access.
  2. Line 7: In C#, this is how you lock a segment of code. Simply use the lock keyword with the locking object (locker) surrounding the sensitive code.

Workaround 2 –  Use a Static Initializer

class 

Program { static void Main(string[] args) { StaticInitializerSingleton sis = StaticInitializerSingleton.CreateInstance(); } }

/// <summary> 
    /// This is the safest and fastest way to design a singleton 
    

/// </summary> public class StaticInitializerSingleton { // Instead of initializing to null, initialize to the new Singleton // public static Singleton Instance = null; public static StaticInitializerSingleton Instance = new StaticInitializerSingleton(); public static StaticInitializerSingleton CreateInstance() { if (Instance == null) Instance = new StaticInitializerSingleton(); return Instance; } // To make sure that no one tries to ‘new’ it private StaticInitializerSingleton() { CreateInstance(); } }


Code Discussion

Instead of initializing to null as we did in our first example, we initialize it to the new Singleton object. This way, we will never have the contention issue on (if instance == null), like we did before. This is the simplest and fastest implementation of a Singleton in C# (the locking implementation above is safe as well – but it has an overhead associated with it).

Private Constructor: Notice the private constructor in the code sample above. If we leave out a constructor, C# provides a default public constructor. So, it would still be possible for someone to do StaticInitializerSingleton  s = new StaticInitializerSingleton (); – which is what we wanted to avoid in the first place. We do not want anyone trying to instantiate our Singleton. We want to limit them to saying ‘CreateInstance’ and we will ensure that only one instance is ever created.

The simplest way to accomplish this is to make our constructor private as shown in the example above.

Summary

The Singleton pattern is one of the most oft used patterns in applications today. People tend to confuse static classes with Singletons. This article clarifies the differences between the two. People also use the Singleton shown in example 1 most frequently. This can cause contention issues – since a Singleton, by its very nature, is a single resource – accessed by multiple clients. While there are different ways to address the Contention problem, the one that provides the best performance and safety combo is the ‘Static Initializer’ Singleton shown in the last example. This example is complete as is – and can be used in your code wherever you desire a Singleton.

Anuj holds professional certifications in Google Cloud, AWS as well as certifications in Docker and App Performance Tools such as New Relic. He specializes in Cloud Security, Data Encryption and Container Technologies.

Initial Consultation

Anuj Varma – who has written posts on Anuj Varma, Hands-On Technology Architect, Clean Air Activist.