I’ll skip over the discussion about why many people hate singletons (that’s a whole separate can of worms, but worth mentioning) because in the end, it’s not going to get rid of them. A singleton is a design pattern that ensures only one instance of the singleton object can ever be constructed. Often, singletons are made to be “globally accessible” in an application (although, I’m still not confident that this is actually part of the definition of a singleton). There are a handful of different ways to implement singletons… so what are they?
The Not-Thread-Safe-Singleton
With singletons, the main goal is to ensure that only one instance can be created. Below is a snippet of singleton code that works, but is not guaranteed in a multi-threaded environment:
internal class NotThreadSafeSingleton { private static NotThreadSafeSingleton _instance; /// /// Prevents a default instance from being created. /// private NotThreadSafeSingleton() { } /// /// Gets the singleton instance (not thread safe). /// internal static NotThreadSafeSingleton Instance { get { if (_instance == null) { _instance = new NotThreadSafeSingleton(); } return _instance; } } }
The key take away point here is that if this singleton class is accessed across multiple threads, it is possible that two threads perform the null check and begin the constructor at the same time. Because this block of code is not protected with a lock a race condition occurs.
The Thread-Safe Singleton
If the key problem with the first example was that it is not safe across threads due to lack of locking… Then it should be pretty obvious that we just need to lock!
internal class ThreadSafeSingleton { private static readonly object _instanceLock = new object(); private static ThreadSafeSingleton _instance; /// /// Prevents a default instance of the class from being created. /// private ThreadSafeSingleton() { } /// /// Gets the singleton instance (thread safe). /// internal static ThreadSafeSingleton Instance { get { if (_instance == null) { lock (_instanceLock) { if (_instance == null) { _instance = new ThreadSafeSingleton(); } } } return _instance; } } }
That looks sort of weird though, doesn’t it? The double-check serves two purposes: a required check for thread safety and a performance optimization! The check inside of the lock actually guarantees that a single instance is created across threads. However, the check outside is an optimization because after the first instance is created, there’s overhead to acquiring the lock just to check if the instance exists.
For what it’s worth, this is actually my preferred method of coding singletons. I’ve been coding them like this for a while in C#, and I find they work nicely. However, I stumbled upon a posting by John Skeet (essentially, a programming god) who’s done a much better job at documenting singleton patterns than I have. In his analysis, he actually notes some drawbacks to this pattern. Firstly, he mentions it doesn’t work in Java, which is a great point. I primarily code in C#, but this is still important to acknowledge. Secondly, he calls upon ECMA CLI memory specifications that state it’s not guaranteed to actually be thread safe without memory barriers. This was slightly out of my comfort zone, so I admit I still have yet to look into this. Finally, I do agree that the pattern is easy to get wrong for more junior developers and as for performance, I’ve never considered it an issue at all. (Hopefully by now you’ve come back from his write-up to finish mine!)
Generic Singleton: A Quick Hand At It…
One of the big drawbacks I saw with the thread safe singleton implementation that I favour is the amount of boilerplate code. Every time I want a new singleton class, I have to code basically everything you see in the previous section. It’s redundant and I don’t want to do it. I can hear the singleton-haters saying “so STOP making them!” but as I said, that’s a discussion for a later post.
I decided I’d have a quick attempt at making a generic singleton! Check out my implementation below (and be warned that I flipped some condition checks in order to try and reduce the width of the text to fit nicely here…):
internal class Singleton<T> where T : class { private static readonly object _instanceLock = new object(); private static T _instance; /// /// Prevents a default instance of the class from being created. /// private Singleton() { } /// /// Gets the singleton instance (thread safe). /// internal static T Instance { get { if (_instance != null) { return _instance; } lock (_instanceLock) { if (_instance != null) { return _instance; } const string SINGLETON_EXCEPTION_MSG = "A single private parameterless constructor is required."; var constructors = typeof(T).GetConstructors( BindingFlags.Public | BindingFlags.CreateInstance | BindingFlags.Instance); if (constructors.Length > 0) { throw new Exception(SINGLETON_EXCEPTION_MSG); } constructors = typeof(T).GetConstructors( BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance); if (constructors.Length != 1 || constructors[0].GetParameters().Length > 0 || !constructors[0].IsPrivate) { throw new Exception(SINGLETON_EXCEPTION_MSG); } _instance = (T)constructors[0].Invoke(null); return _instance; } } } }
Doesn’t look to shabby, right? You simply need to create a class with *only* a private constructor and everywhere you want access to the singleton, you say Singleton.Instance. It’s that easy.
Unfortunately, this isn’t as good as I initially hoped. Can you think of an example where this approach breaks down? My hint to you is everything you need to break it is posted right here. Unfortunate really because I thought I was onto something good there! 🙂 In reality, it may not be a bad foundation for your singleton implementations if you don’t like the boiler plate code I listed above.
Wrapping Up How To Structure Singletons
There are many ways to write singletons, and some are clearly more robust than others. I’ve only shown you a couple here, but John Skeet’s post has a handful more which he prefers. It’s hard to argue with what he’s written (although, I’m not actually fond of his fourth implementation which he likes) because he’s done a great analysis on them. In the end, it’s important to know what a singleton actually is, when you might want to use it, and what the differences actually mean in various implementations.