none
Question of thread-safe singleton pattern? RRS feed

  • Question

  • Dear All,

    There is a little question about thread-safe singleton pattern,

    https://msdn.microsoft.com/zh-tw/library/ff650316.aspx?f=255&MSPPError=-2147217396

    The code is referred to the link above,

    my question is since instance is null, and use syncRoot object to lock this code block,

    why another check condition if (instance == null) is added for creating a Singleton instance? I don't quite understand. If the internal check block of lock(synRoot) is removed as follows, is it possible?

                public static Singleton GetInstance()
                {
                    if (instance == null)
                    {
                        lock (syncRoot)
                        {
    
                            /* if (instance == null) ? */
                                instance = new Singleton();
    } } return instance; }

    Thanks.

    Thanks and Best regards,

    E-John

    namespace TestSingleton
    {
        class Program
        {
            class Singleton
            {
                private static Singleton instance = null;
                private static object syncRoot = new Object();
    
                private Singleton() { }
    
                public static Singleton GetInstance()
                {
                    if (instance == null)
                    {
                        lock (syncRoot)
                        {
                            if (instance == null)
                                instance = new Singleton();
                        }
                    }
                    return instance;
                }
            }
    
            static void Main(string[] args)
            {
                Singleton s1 = Singleton.GetInstance();
                Singleton s2 = Singleton.GetInstance();
    
                if (s1 == s2)
                {
                    Console.WriteLine("s1 hash code : {0}", s1.GetHashCode());
                    Console.WriteLine("s2 hash code : {0}", s2.GetHashCode());
                    Console.WriteLine("Same instance");
                }
    
                Console.ReadLine();
            }
        }
    }






    • Edited by E-John Friday, May 4, 2018 8:30 AM
    Friday, May 4, 2018 7:39 AM

Answers

  • If two or more threads reach this function almost simultaneously, and no instance available yet, then only one of them will go to ‘new Singleton’. The other ones will wait at lock. Then the thread that created the instance exits the lock block. This allows some other waiting thread to enter the block. In this case, if the second ‘if’ is not present, then the thread will incorrectly create another instance of the object, which is not permitted for singletons. In order to avoid this, the ‘if’ should not be removed.

    However, it is possible to delete the first ‘if’. It is added for optimisation, to avoid the locking intervals if the object is already created.

     

    • Edited by Viorel_MVP Friday, May 4, 2018 10:57 AM
    • Proposed as answer by Petr B Friday, May 4, 2018 3:21 PM
    • Marked as answer by E-John Tuesday, May 8, 2018 3:28 PM
    Friday, May 4, 2018 10:45 AM
  • That link is really old and completely out of date. That isn't how you build a singleton in C#.

    public class MySingleton
    {
       private MySingleton () { }
    
       public static readonly MySingleton Instance = new MySingleton();
    }

    Guaranteed thread safe by the CLR with no locking needed (by your code). The instance is created by the CLR before it is referenced the first time. If you need delayed initialization then you could use Lazy<T> as well.


    Michael Taylor http://www.michaeltaylorp3.net

    • Proposed as answer by Fei HuModerator Tuesday, May 8, 2018 2:56 AM
    • Marked as answer by E-John Tuesday, May 8, 2018 3:36 PM
    Friday, May 4, 2018 2:15 PM
    Moderator

All replies

  • If two or more threads reach this function almost simultaneously, and no instance available yet, then only one of them will go to ‘new Singleton’. The other ones will wait at lock. Then the thread that created the instance exits the lock block. This allows some other waiting thread to enter the block. In this case, if the second ‘if’ is not present, then the thread will incorrectly create another instance of the object, which is not permitted for singletons. In order to avoid this, the ‘if’ should not be removed.

    However, it is possible to delete the first ‘if’. It is added for optimisation, to avoid the locking intervals if the object is already created.

     

    • Edited by Viorel_MVP Friday, May 4, 2018 10:57 AM
    • Proposed as answer by Petr B Friday, May 4, 2018 3:21 PM
    • Marked as answer by E-John Tuesday, May 8, 2018 3:28 PM
    Friday, May 4, 2018 10:45 AM
  • That link is really old and completely out of date. That isn't how you build a singleton in C#.

    public class MySingleton
    {
       private MySingleton () { }
    
       public static readonly MySingleton Instance = new MySingleton();
    }

    Guaranteed thread safe by the CLR with no locking needed (by your code). The instance is created by the CLR before it is referenced the first time. If you need delayed initialization then you could use Lazy<T> as well.


    Michael Taylor http://www.michaeltaylorp3.net

    • Proposed as answer by Fei HuModerator Tuesday, May 8, 2018 2:56 AM
    • Marked as answer by E-John Tuesday, May 8, 2018 3:36 PM
    Friday, May 4, 2018 2:15 PM
    Moderator
  • Hi Viorel,

    Now I get it. Thanks for your detailed explanation.

    Thanks and Best regards,

    E-John

    Tuesday, May 8, 2018 3:28 PM
  • Hi CoolDadTx,

    Thanks for providing the new way for thread-safe singleton creation by CLR.

    Thanks and Best regards,

    E-John

    Tuesday, May 8, 2018 3:36 PM