Code that accompanies this article can be downloaded here.
The Singleton Pattern is probably the most well-known design pattern that came out of Gang of Four’s book Design Patterns: Elements of Reusable Object-Oriented Software. This pattern is one of the creational patterns, and basically, it ensures that only one object of a particular class is created and shared among other members of the system. Singleton class should enable easy access to its only instance to the other classes.
But this design pattern carries a lot of controversies too. Some consider it an antipattern and cause of code smell. Among many complaints, people often argue that it violates Single Responsibility Principle, due to the fact that it handles its own creation, that it couples code and that it is hard to test. And even though some of these issues were addressed by Uncle Bob himself, there are a lot of good points that Singleton class shouldn’t be used. Heck, there is a good chance that people will hate you just by writing one. But…
Singleton patterns still solve one problem that you may encounter – Resource Contention. This is a situation where you need one instance of the object and you need to manage that instance. There are not many cases of this situation and one example of this is a single log file. There are suggestions that you can solve this problem with Dependency Injection which you should also consider. But, in case you need Singleton, let’s take a look at some good and bad ways to implement Singleton class.
Standard Implementation
Singleton pattern is also one of the most commonly asked interview questions. Usually, candidates are asked to write one version of singleton implementation. If you Google this, you’ll probably find few hits that will suggest an implementation that looks like this:
using System;
namespace SingletonExamples
{
public class Singleton
{
private static Singleton _instance;
private Singleton() { }
public static Singleton Instance
{
get
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
}
Now this will probably pass as a fine answer on an interview, but this code definitely has a lot of problems, apart from not being a very impressive one. The biggest problem is that this code isn’t thread-safe, and that is why you shouldn’t use this code. Yes, now you are using threads and Singleton and everyone will avoid you in the office. Nevertheless, let’s go through this thought exercise. We don’t want to end up in the situation where two threads evaluate if (_instance == null)
as true
and each creates an instance of the class.
Thread-safe Implementation
So, let’s do something like this:
using System;
namespace SingletonExamples
{
public class Singleton
{
private static Singleton _instance;
private static readonly object _lock = new object();
private Singleton() { }
public static Singleton Instance
{
get
{
lock (_lock)
{
if (_instance == null)
{
_instance = new Singleton();
}
return _instance;
}
}
}
}
}
There it is, we used locks to make our singleton class thread-safe. But, locks are not very good synchronization mechanisms in this case. Because the lock is required everytime Instance is asked for, the performance of this code will be degraded. This problem can be avoided if we ask if the instance is null
before locking and then asking is instance null
once again after acquiring the lock. Now, that would look ugly. Also, we already have one if
-null
combo, and we can agree that controlling flow with if
-null
combos is not such a good idea and that it indicated that we have problems in our design.
Can we try to use the static
constructor?
Implementation with Static Constructor
Static
constructors will assure that it has been run only once per application domain, meaning that our Singleton
class can look like this:
public class Singleton
{
private static Singleton instance;
private Singleton() { }
static Singleton()
{
instance = new Singleton();
}
public static Singleton Instance
{
get { return instance; }
}
}
The first thread that wants to get property Instance
will trigger static
constructor, also known as type initializer. Other threads that try to read the Instance
property will be locked until static
constructor has finished. Only once it completes its task, other threads will be allowed to get Instance
value. So, locking on every time someone tries to get an instance is avoided.
But… people will have a lot of comments on that static
constructor of yours. Usually, something along the line that they could cause deadlocks if you perform blocking operations, e.g., asynchronous callbacks.
Can we avoid this? If we are working in C# 4 or above, we can. And we can achieve this by using – Lazy.
Lazy Implementation
Lazy initialization of an object means that object creation is deferred until it is first used. This way of object construction is used primarily for optimization purposes. In .NET 4 and above, we can use Lazy
class, which encapsulates this kind of behavior. It is also thread-safe, so we don’t have to worry about multiple threads creating duplicate objects.
So, Singleton implementation using Lazy
would look like this:
using System;
namespace SingletonExamples
{
public class Singleton
{
private static readonly Lazy<Singleton> instance =
new Lazy<Singleton>(() => new Singleton());
public static Singleton Instance
{
get
{
return instance.Value;
}
}
private Singleton()
{
}
}
}
Conclusion
Singleton is for sure one pattern with many flaws. The problem is also that this pattern is often used in places not quite suited for it, thus coupling code, and adding performance issues. However, it has its purpose and its (rare) use.
And although there are multiple variations of Singleton implementation, I personally, prefer the last version of implementation. It is simplest, thread-safe solution with lazy initialization, that everyone can understand. Also, I need to add once again that first implementation shouldn’t be used ever.
This work is licensed under a Creative Commons Attribution 4.0 International License.