Raghav55
Raghav55

Reputation: 3135

double check locking in singleton pattern

it may be basic question

to have a singleton in multi-threaded environment we can use a lock. Please refer the code snippet. But why do we need double-checked locking in singleton pattern? And more what does double-checked locking means?

class singleton
{
    private static singleton instance = null;
    private static singleton() { }

    private static object objectlock = new object();

    public static singleton Instance
    {
        get
        {

            lock (objectlock) //single - check lock
            {
                if (instance == null)
                {
                    instance = new singleton();
                }

                return instance;
            }
        }

    }
}

Upvotes: 22

Views: 29692

Answers (6)

TcKs
TcKs

Reputation: 26632

The "best" way I know is this:

public class MySingleton {
    // object for synchronization
    private static readonly object syncRoot = new object();
    // the singleton instance
    private static MySingleton @default;

    public static MySingleton Default {
        get {
            // geting singleton instance without locking
            var result = @default;
            // if result is NOT null, no additional action is required
            if ( object.ReferenceEquals(result, null) ){
                // lock the synchronization object
                lock(syncRoot) {
                    // geting singleton instanc in lock - because
                    // the value of @default field could be changed
                    result = @default;

                    // checking for NULL
                    if ( object.ReferenceEquals(result, null) ) {
                        // if result is NULL, create new singleton instance
                        result = new MySingleton();
                        // set the default instance
                        @default = result;
                    }
                }
            }

            // return singleton instance
            return result;
        }
    }
}

Upvotes: 4

Sachin Mishra
Sachin Mishra

Reputation: 1183

When we try to execute the method of the singleton class using Parallel libraries. It doesn’t recognize the singleton behavior because of multi threading is executing in TPL which causes to failure of concept Singleton Pattern . To overcome this problem there is concept of the locking of the object so that at a time only one thread can access it. But this is not efficient approach because involvement of lock checking creates unnecessary watches to the object. To avoid it we make use “Double locking checking”

enter image description here

Upvotes: 2

Pramod Gupta
Pramod Gupta

Reputation: 91

Multithreaded Singleton : The best approach to use double check locking

public sealed class Singleton
{
   private static volatile Singleton _instance;
   private static readonly object InstanceLoker= new Object();

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (_instance == null) 
         {
            lock (InstanceLoker) 
            {
               if (_instance == null) 
                  _instance = new Singleton();
            }
         }

         return _instance;
      }
   }
}

Upvotes: 6

Jimmy Zimms
Jimmy Zimms

Reputation: 121

And with .Net 4.x and newer you should defer to the Lazy class when possible as this pattern is used with the Initialization And Publication option. (note: the inverse is available as well where creation isn't thread safe but the publication of the instance is via the Publication option)

Upvotes: 5

Danny Tuppeny
Danny Tuppeny

Reputation: 42343

If you create the object in the field initialiser, you don't need the lock:

class singleton
{
    private static singleton instance = new singleton();
    private static singleton() { }

    public static singleton Instance
    {
        get { return instance; }
    }
}

Also - bear in mind that the lock is only controlling the creation of the object, the object would still need to be thread-safe if you're using it in multiple threads.

Upvotes: 3

SLaks
SLaks

Reputation: 887453

Jon Skeet explains this in detail.

Locks are expensive.
If the object already exists, there's no point in taking out a lock.
Thus, you have a first check outside the lock.

However, even if the object didn't exist before you took the look, another thread may have created it between the if condition and the lock statement.
Therefore, you need to check again inside the lock.

However, the best way to write a singleton is to use a static constructor:

public sealed class Singleton
{
    private Singleton()
    {
    }

    public static Singleton Instance { get { return Nested.instance; } }

    private class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
} 

Upvotes: 32

Related Questions