简体   繁体   中英

Why this realization of Singleton Pattern can have two instances

I am learning Singleton Pattern. On msdn the first realization of Singleton Pattern is:

public class Singleton
{
   private static Singleton instance;

   private Singleton() {}

   public static Singleton Instance
   {
      get 
      {
         if (instance == null)
         {
            instance = new Singleton();
         }
         return instance;
      }
   }
 public void Display()
    {
        Console.WriteLine("This is from Singleton!");
    }
}

The main disadvantage of this implementation, however, is that it is not safe for multithreaded environments. If separate threads of execution enter the Instance property method at the same time, more that one instance of the Singleton object may be created.

I tried to create two instances of this class:

Console.WriteLine("First Instance!");
Singleton s = Singleton.Instance;
s.Display();

Console.WriteLine("Second Instance!");
Singleton ss = Singleton.Instance;
ss.Display();

Console.ReadLine();

Both "s" and "ss" are created so I guess I misunderstand something. Can you please let me know why two instances are created?

In this case you are not creating two instances. Instead you create two variables pointing to the same instance. The first call Singleton s = Singleton.Instance; creates the instance. The second call just gives back the same instance. If you give the singleton class another field (lets call it string text) and then call s.text = "a"; ss.text will also have the value "a";

To make the whole thing thread safe you could take a look at the Mutex class for example.

In the code segment, if(instance == null) check will be fine to create single instance of the class only if the module is accessed by single thread always.

But in case of multiple threaded environment, it will fail and will be resulted in multiple instance of the Singleton Class.

Say T1 and T2 are two threads which are accessing the get method simultaneously at some moment.

get 
{
    if (instance == null)
    {
        instance = new Singleton();
    }
    return instance;
}

The explanation is as below:

  1. When T1 executes if(instance == null) , and enters inside if block if instance is not yet initialized.
  2. At the same time, if T2 also executes if(instance == null) line, just when T1 enters the block (T1 is yet to execute instance = new Singleton() )
  3. Both the threads will be allowed inside if block.
  4. Both threads will be able to create two difference instances of Singleton Class.

The correct way to work with multiple threads here will be as below-

get 
{
    if (instance == null)
    {
        lock();
        if (instance == null)
        {
            instance = new Singleton();
        }
        unlock();
    }
    return instance;
}

Two (or even more) separate threads can get to if (instance == null) check at same time. Both checks will return true if instance not exists yet. Then both threads will go further, and each will create its own instance of class.

Solution: Double-checked locking

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM