Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Thread Safe C# Singleton Pattern

I have some questions regarding the the singleton pattern as documented here: http://msdn.microsoft.com/en-us/library/ff650316.aspx

The following code is an extract from the article:

using System;  public sealed class Singleton {    private static volatile Singleton instance;    private static object syncRoot = new object();     private Singleton() {}     public static Singleton Instance    {       get        {          if (instance == null)           {             lock (syncRoot)              {                if (instance == null)                    instance = new Singleton();             }          }           return instance;       }    } } 

Specifically, in the above example, is there a need to compare instance to null twice, before and after the lock? Is this necessary? Why not perform the lock first and make the comparison?

Is there a problem in simplifying to the following?

   public static Singleton Instance    {       get        {         lock (syncRoot)          {            if (instance == null)                instance = new Singleton();         }           return instance;       }    } 

Is the performing the lock expensive?

like image 857
Wayne Phipps Avatar asked Sep 07 '12 10:09

Wayne Phipps


People also ask

What is thread-safe in C?

Thread safety A threadsafe function protects shared resources from concurrent access by locks. Thread safety concerns only the implementation of a function and does not affect its external interface. The use of global data is thread-unsafe.

Is C write thread-safe?

write() is certainly thread-safe. The problem is that a partial write() could require multiple calls in order to completely write the data, and while that is "thread-safe" it could result in interleaved data.

Is ++ thread-safe in C?

++ is not defined as thread-safe.


1 Answers

Performing the lock is terribly expensive when compared to the simple pointer check instance != null.

The pattern you see here is called double-checked locking. Its purpose is to avoid the expensive lock operation which is only going to be needed once (when the singleton is first accessed). The implementation is such because it also has to ensure that when the singleton is initialized there will be no bugs resulting from thread race conditions.

Think of it this way: a bare null check (without a lock) is guaranteed to give you a correct usable answer only when that answer is "yes, the object is already constructed". But if the answer is "not constructed yet" then you don't have enough information because what you really wanted to know is that it's "not constructed yet and no other thread is intending to construct it shortly". So you use the outer check as a very quick initial test and you initiate the proper, bug-free but "expensive" procedure (lock then check) only if the answer is "no".

The above implementation is good enough for most cases, but at this point it's a good idea to go and read Jon Skeet's article on singletons in C# which also evaluates other alternatives.

like image 100
Jon Avatar answered Sep 19 '22 03:09

Jon