Last updated on September 15, 2023
What is the singleton pattern?
The singleton design pattern is a technique to ensure there is only ever one instance of a particular class in your program.
If you prefer learning with videos, you can watch the lesson here:
Why would you use a singleton?
You might want to use the singleton pattern for classes that use an external resource, and there might be problems if multiple objects try to use that resource at the same time. For example, the file system, a database server, a web service, etc.
If your program needs to do logging, you may want all output to be written to one log file. That could lead to resource conflicts and errors.
With a singleton logger object, you don’t need to worry about several different objects trying to write to the same file, at the same time.
Alternatives to the singleton pattern
Another option is to use a global, or static, class. But that usually leads to bad programming practices. After a while, those classes tend to hold a lot of unrelated information and objects.
This can still happen with singletons, which is why some programmers say singletons are an “anti-pattern” – a bad programming practice.
There are times where singletons can be useful. However, like many programming decisions, you need to consider the positives and negatives.
Plus, you can more easily create “mock” versions of your singleton class, for unit testing. This is difficult to do with static classes.
Code samples
Let’s say we are writing a program that manages customer data. Whenever a customer address is changed, we want to create an entry in a log file.
Here is the Customer class, when we are not using the Singleton design pattern. In this first example, we create a new Logger object for each Customer.
Customer.cs
using System; namespace DesignPatternDemos.Singleton { public class Customer { private readonly Logger _logger; public string Name { get; set; } public Customer(string name) { _logger = Logger.GetLogger(); Name = name; } public void UpdateAddress(string streetAddress, string city) { // Pretend we update the database, and/or do other things here. // Now, write a log message, so we have a record of the update. _logger.WriteMessage(string.Format("Updated the address for: {0} at: {1}", Name, DateTime.Now)); } } }
Logger.cs
namespace DesignPatternDemos.Singleton { public class Logger { // Make the constructor private, to force instantiation through the factory design pattern private Logger() { } // Factory method, that returns a new Logger object public static Logger GetLogger() { return new Logger(); } // Pretend we're writing the message to a file here. public void WriteMessage(string message) { } } }
With this code, our program might create thousands of Logger objects, and any one of them may try to write to the file at the same time as another Logger object. This could lead to a conflict.
So, we’ll use the Singleton design pattern to create a Logger class that can only be instantiated once. Each Customer will point to that single Logger object.
The basic idea is that the factory method will check to see if an instance of the object exists. If it does not, it will create the object and return it. If the object already exists, the factory method will return that single, already-instantiated object, instead of creating a new one.
Bad attempt at creating a singleton (DO NOT USE THIS CODE)
I’m posting this code as an image, so no one copy-pastes it into their program.
This uses a static variable for the object to be returned. The factory method (GetLogger), checks to see if the object is null. If it is, the method creates a new instance of the Logger object, assigns it to the private static variable, and returns it. If the object is not null (it already exists), it will return it.
However, this version is unsafe, because multiple objects might call the GetLogger method at the same time. Due to timing/threading, two objects might do their check if _logger is null at the same time. So, they would both see the value is null, and both try to create a new Logger object.
In this small sample project, that isn’t a real problem. But, if your program expects a single instance of the Logger object, this could lead to problems – ones that probably won’t be detected until the program is run in “the real world”.
Singleton design pattern (double-locking technique)
This is a common way to do a safe singleton – a double-lock.
namespace DesignPatternDemos.Singleton { public sealed class Logger { private static Logger _logger; private static readonly object _syncLock = new object(); private Logger() { } public static Logger GetLogger() { if(_logger == null) { lock (_syncLock) { if(_logger == null) { _logger = new Logger(); } } } return _logger; } public void WriteMessage(string message) { } } }
Even if you have multiple objects, on multiple threads, calling the GetLogger method, one of them will be “first”. This first object will see that the _logger is null, then attempt to get a lock on the _syncLock variable. Only one object at a time can have a lock on an object. Any other objects that try to lock the _syncLock variable will be queued up, until the first object releases its lock.
With the double-lock method, if two objects call GetLogger at the same time, the “first” one gets a lock on the _syncLock variable, checks that _logger is still null, creates a new Logger object (and assigns it to _logger), then it releases its lock (by reaching the closing curly-brace of the “lock” section of code).
With the lock released, the second object will get its lock, then re-check if _logger is null. This time, it won’t be null, since the first object already instantiated it. So, the second object does not try to create a new instance. Instead, it releases its lock, and returns the existing _logger object.
By the way, there is nothing special about the _syncLock variable. It’s a normal object. We only need a shared object that the calling code can “lock”, in order to only allow one thread at a time to finish running the code inside the curly braces of the lock().
If you are using the .NET Framework version 1.1 (or earlier), you may want to change the _logger declaration line to this:
private static volatile Logger _logger;
Making the _logger object “volatile” is another bit of thread-safety, that also does its own form of locking, to ensure that every thread uses the most recent value of the object. However, it is not needed with .NET 2.0, or later.
Using the double-lock method keeps your singleton thread-safe.
Singleton design pattern (static initialization technique)
If you’re using C#, you can use a simpler method than the double-lock – static initialization. This method is does not work in all other languages; however, the .NET framework explicitly is designed to allow this to work.
namespace DesignPatternDemos.Singleton { public sealed class Logger { private static readonly Logger _logger = new Logger(); private Logger() { } public static Logger GetLogger() { return _logger; } public void WriteMessage(string message) { } } }
In this technique, you just initialize the private static readonly _logger variable with an instance of the Logger object, in the same line where you declare it. Then, the GetLogger method returns that value.
This is the simplest way to implement the singleton design pattern in a .NET language.
Real-world example where I used the singleton pattern
One program I worked on was a web service that received orders, translated them for other programs, and submitted them to the other programs.
If we created a new object for each submission to the next program, we might have hundreds objects trying to simultaneously submit requests to those programs. That could cause a problem, if the other programs were not capable of handling as many connections as we had orders.
So, we used a singleton, with a queue, to submit orders to the next system. Our single object would accept all orders, hold them in a queue, and submit one at a time to the next program. This allowed our system to handle more submissions than the other systems could handle.
Related design patterns
The Factory Pattern – The singleton design pattern uses a special form of the factory design pattern to ensure that only one instance of an object is ever created.
How do we handle the exceptions that is logged while creating singleton object ? We have a situation where we create a singleton object using static constructor (we are not into multi-thread app), however when the crash occurs we get different call stack than what occured in static constructor. Something like typeinitialization exception over the actual instance invocation exception
Yes, it throws a strange exception, if the static “constructor” has an error.
When that happens, I set a breakpoint at the first line in the “constructor” – and use F10 to step through the code, when it runs. The constructor usually calls other static functions, so I need to add a breakpoint at the first line of the function that fails (which I know, because it was the last function called in the “constructor”).
Please tell me if you still have questions. I can make a short video, showing exactly how I do this.
Can you show me the sample that you talked about one program pass info to other program using singleton queue?
I don’t have that source code. It was for a client many years ago. But, if you wanted to do something like that, you might want to look at a message queue like MSMQ or RabbitMQ.