Yesterday I was viewing a video (Spanish) that explains about how to implement the Singleton pattern in .NET. After some implementations the video ends up showing the best way to have a thread safe implementation of the singleton pattern.
The problem is the video ends saying that the next two implementations are exactly the same on a functional level, which is not completely true.
Implementation 1
1: public sealed class Singleton1
2: { 3: private DateTime creationTime;
4: private static Singleton1 instance = null;
5: private static object synchro = new object();
6:
7: private Singleton1()
8: { 9: creationTime = System.DateTime.Now;
10: }
11:
12: public static Singleton1 Instance
13: { 14: get
15: { 16: if (instance == null)
17: { 18: lock (synchro)
19: { 20: if (instance == null)
21: { 22: instance = new Singleton1();
23: }
24: }
25: }
26:
27: return instance;
28: }
29: }
30:
31: public string CreationTime
32: { 33: get
34: { 35: return creationTime.ToString("hh:mm:ss.ffffff"); 36: }
37: }
38: }
Implementation 2
1: public sealed class Singleton2
2: { 3: private DateTime creationTime;
4: private static Singleton2 instance = new Singleton2();
5:
6:
7: private Singleton2()
8: { 9: creationTime = System.DateTime.Now;
10: }
11:
12: public static Singleton2 Instance
13: { 14: get
15: { 16: return instance;
17: }
18: }
19:
20: public string CreationTime
21: { 22: get
23: { 24: return creationTime.ToString("hh:mm:ss.ffffff"); 25: }
26: }
27: }
The second implementation is correct, since it shows how you can avoid the lock while creating the object instance of the Singleton class. The reason why this is thread safe is because .NET guarantees that the Type Constructor (or Type Initializer on the ECMA standard) is executed only once per AppDomain and is thread-safe.
Regardless both of them are thread-safe, the difference is that the first one is lazy loaded while the second one is eager loaded. In order to implement the singleton pattern using a lazy loaded version and still take profit of the Type Constructors, you need to add a container for the object instance of Singleton2. Doing this the Type Constructor will only be initialized when you access the property (or any other member making reference to it). Below you can see the correct implementation for it.
1: public sealed class LazyLoading
2: { 3: private DateTime creationTime;
4:
5: private LazyLoading()
6: { 7: creationTime = DateTime.Now;
8: }
9:
10: public static LazyLoading Instance
11: { 12: get
13: { 14: return SingletonContainer.instance;
15: }
16: }
17:
18: public string CreationTime
19: { 20: get
21: { 22: return creationTime.ToString("hh:mm:ss.ffffff"); 23: }
24: }
25:
26: class SingletonContainer
27: { 28: internal static readonly LazyLoading instance =
29: new LazyLoading();
30: }
31: }