Using the Singleton Pattern
Software Development March 26th, 2008Chances are if you’ve heard of any design pattern, it’s this one. There seems to be a lot of negative comments concerning the singleton pattern. I’ve heard of it referred to as nothing but a global variable, and I’ve also heard that using a singleton in the first place is poor design. I’m going to have to agree to disagree with these people. I will agree that this pattern is often overused, but in my opinion it has it’s uses.
The singleton design pattern is actually a pretty simple concept. It just means that you are restricting the instantiation of a class to a single instance. Before we get into the implementation of the pattern, let’s figure out why we would use it. This pattern should be used when you need one and only one instance of a class. In my opinion, one of the biggest mistakes people make is implementing this pattern because they “only need 1 instance”. If this is why you chose this pattern, then chances are that there is a better way to design your application. The question you should be asking yourself is, “Will something VERY VERY bad happen if there is more than 1 instance?”
1: namespace Singleton
2: {
3: public sealed class Foo
4: {
5: // This is the instance to our class.
6: static Foo _instance = null;
7:
8: // A private constructor means that it can't
9: // be instantiated from outside the class.
10: private Foo()
11: {
12:
13: }
14:
15: // This property allows us to get access
16: // to the singleton. It only creates a
17: // new instance the first time.
18: public static Foo Instance
19: {
20: get
21: {
22: if (_instance == null)
23: _instance = new Foo();
24:
25: return _instance;
26: }
27: }
28: }
29: }
Above is one possible implementation of the singleton pattern. Notice, our class Foo is sealed, because I don’t want to allow anyone to inherit from it. I made the constructor private, this means that you will not be able to create an instance of this class with the new operator when you use it. Instead, to get an instance of the class you need to go through the property. That is the key to implementing this pattern. You need to control instantiation through either a property or a method. (I chose to use a property) This is an example of how you would get an instance to Foo:
1: namespace Singleton
2: {
3: class Program
4: {
5: static void Main(string[] args)
6: {
7: // Get the instance to our singleton.
8: Foo foo1 = Foo.Instance;
9: }
10: }
11: }
I needs to be pointed out though, our implementation of the singleton pattern has a big problem that may not be apparent. It is not thread safe, meaning that if you were to try to get instances from multiple threads, you could get multiple instances rather than the one instance which is our goal. This is a pretty easy obstacle to overcome in C# using locking. Making this change makes our singleton thread safe:
1: namespace Singleton
2: {
3: public sealed class Foo
4: {
5: // This is the instance to our class.
6: static Foo _instance = null;
7:
8: // This will serve as a lock to make our
9: // singleton thread safe.
10: static readonly object _mutex = new object();
11:
12: // A private constructor means that it can't
13: // be instantiated from outside the class.
14: private Foo()
15: {
16:
17: }
18:
19: // This property allows us to get access
20: // to the singleton. It only creates a
21: // new instance the first time.
22: public static Foo Instance
23: {
24: get
25: {
26: // This lock allows thread safety.
27: lock (_mutex)
28: {
29: if (_instance == null)
30: _instance = new Foo();
31:
32: return _instance;
33: }
34: }
35: }
36: }
37: }
So now we have our singleton, how do know for sure that we’re only getting 1 instance? I put together a quick test to prove exactly that. First, I modified the Foo class so that is has a GUID variable that is assigned when the instance is created. The reasoning for this is that if we get the same GUID back every time I load the SingleCheck property I must have the same instance back, since generating 2 identical GUID’s is impossible.
1: namespace Singleton
2: {
3: public sealed class Foo
4: {
5: // This is the instance to our class.
6: static Foo _instance = null;
7:
8: // This will serve as a lock to make our
9: // singleton thread safe.
10: static readonly object _mutex = new object();
11: static Guid _singleCheck;
12:
13: // A private constructor means that it can't
14: // be instantiated from outside the class.
15: private Foo()
16: {
17:
18: }
19:
20: // This property allows us to get access
21: // to the singleton. It only creates a
22: // new instance the first time.
23: public static Foo Instance
24: {
25: get
26: {
27: // This lock allows thread safety.
28: lock (_mutex)
29: {
30: if (_instance == null)
31: {
32: _instance = new Foo();
33: _singleCheck = System.Guid.NewGuid();
34: }
35:
36: return _instance;
37: }
38: }
39: }
40:
41: public Guid SingleCheck
42: {
43: get { return _singleCheck; }
44: }
45: }
46: }
After I had the singleton ready, I created a console application that creates a few instances to Foo, and threw in a couple BackgroundWorker objects to test some threading.
1: namespace Singleton
2: {
3: class Program
4: {
5: static void Main(string[] args)
6: {
7: // Get the instance to our singleton.
8: Foo foo1 = Foo.Instance;
9: Foo foo2 = Foo.Instance;
10: Foo foo3 = Foo.Instance;
11: Foo foo4 = Foo.Instance;
12:
13: Console.WriteLine("foo1: " + foo1.SingleCheck.ToString());
14: Console.WriteLine("foo2: " + foo2.SingleCheck.ToString());
15: Console.WriteLine("foo3: " + foo3.SingleCheck.ToString());
16: Console.WriteLine("foo4: " + foo4.SingleCheck.ToString());
17:
18: // Check threading.
19: BackgroundWorker worker1 = new BackgroundWorker();
20: BackgroundWorker worker2 = new BackgroundWorker();
21: worker1.DoWork += new DoWorkEventHandler(doThreadWork1);
22: worker2.DoWork += new DoWorkEventHandler(doThreadWork2);
23: worker1.RunWorkerAsync();
24: worker2.RunWorkerAsync();
25:
26: Console.ReadLine();
27: }
28:
29: static void doThreadWork1(object sender, DoWorkEventArgs e)
30: {
31: Foo threadFoo = Foo.Instance;
32: Console.WriteLine("threaded (1): " + threadFoo.SingleCheck.ToString());
33: }
34: static void doThreadWork2(object sender, DoWorkEventArgs e)
35: {
36: Foo threadFoo = Foo.Instance;
37: Console.WriteLine("threaded (2): " + threadFoo.SingleCheck.ToString());
38: }
39:
40: }
41: }
This was the output of my test, it shows that we were getting the same instance back each time.
There is one last thing I’d like to touch on concerning the use of this pattern. Remember the golden rule…..requirements change. Even though when you created your singleton it was absolutely necessary, a year from now your application may change and the use of a singleton is no longer necessary. You can use this pattern in your code in a way that minimizes the impact of a change like this.
1: // Control places in the code that
2: // get the instance of Foo.
3: Foo myFoo = Foo.Instance;
4:
5: // That way you can treat it like a normal
6: // object when you use it. This makes a change
7: // easier since you only have to worry about the
8: // declaration.
9: myFoo.DoSomething();
10: myFoo.DoSomethingElse();
11:
12: // This syntax is valid and will work,
13: // but it makes a change harder because
14: // there are more places in your code
15: // that depend on Foo being a Singleton.
16: Foo.Instance.DoSomething();
17: Foo.Instance.DoSomethingElse();
Hopefully now you have a grasp on what the singleton design pattern is, and how to implement it. I’ll leave you with this piece of advice, because this design pattern is definitely overused. Don’t let everything start to look like a nail just because you have a hammer!
March 26th, 2008 at 12:35 pm
Just so it’s not stated a million times…….I realize I should have written unit tests rather than just testing with a console app.
March 26th, 2008 at 2:06 pm
I like to see the thread safety version of this pattern, although I would include that unless you need thread safety don’t implement it. It’s just extra overhead that isn’t needed.
-Jamin
http://www.jaminroth.com
March 26th, 2008 at 2:51 pm
See http://www.yoda.arachsys.com/csharp/singleton.html for much simpler implementations of a thread-safe singleton in C#.
March 26th, 2008 at 3:02 pm
@Peter:
That is a good article, he goes into much more detail than I did with different ways to do it. I will have to disagree about it being a “simpler” implementation, especially since my thread-safe version is basically the same thing as his second example. (in fact, they are almost identical)
March 27th, 2008 at 2:11 am
Here is another perspective:
http://en.csharp-online.net/Singleton_design_pattern
March 27th, 2008 at 8:35 am
@Hyle,
That is another example of how to do it. In that article, they use a method rather than a property to get an instance to the singleton. It works either way.
March 31st, 2008 at 3:22 am
You implementation with the mutex while thread safe is not very efficient.
Singletons are instantiated once but used many times so it is better to only lock if the instance is null (and then check again since potentially multiple threads can get there. plus you’d also have to mark the instance volatile in that case)
In any event, if you don’t need the lazy initialization you can just do
public static readonly MySingleton instance = new MySingleton()
and the CLR will take care of everything for you.
Lastly, if you are going to implement a singleton it is better to implement a “template” one using Generics and then just initialize it with the type you want. This is a better approach from the SRP perspective
Arnon
March 31st, 2008 at 9:26 am
@Arnon,
You are right that the lazy initialization isn’t necessary, and you’re solution will work. Lazy initialization is nice if your constructor does anything time consuming.
As for the point on efficiency….I’ll grant you the point that locking is not efficient, but some performance tests were done in the link that Peter pointed out. The author of that article has a locking solution very similiar to the one I came up with, and in his benchmark he was able to acquire the singleton a billion times in under 40 seconds. To me, that performance is more than good enough.
I do like your idea with generics, I might have to explore that a little and come back with a follow up post.