C# Singleton Design Pattern in Multi-threaded Environment

C# Singleton Design Pattern in Multi-threaded Environment

Singleton means that only the class can create only one instance. In the entire application, single instance is shared among all the threads.

The below program is thread safe in a single threaded environment.

namespace DesignPatternSingleton
{
    class MyFirstDesign
    {

       private MyFirstDesign() {}
        
       private static MyFirstDesign _myInstance;
 
       public static MyFirstDesign MyInstance()
       {
           if(_myInstance == null)
           {
              _myInstance = new MyFirstDesign();
           }
           
           return  _myInstance;

        }
      

    }

}        

Rules

1. Single constructor – private & parameterless

a) It shouldn’t be subclassed. If it is subclassed, it will create an instance and violates the rule.

b) Only the class should be able to create instance. So the constructor is defined as private. This also means no other class can create this instance.

c) It shouldn’t have any parameter in the constructor.

2. The type of class is known up front. If the type is known during run time, it is a factory class.

3. Static variable holds the reference to the single created instance.

4. Public static method MyInstance() to get the reference to the created instance

5. Only one thread can create an instance. When the next thread tries to call the MyInstance() after first thread successfully created the instance, it will return the created instance.

What if two threads attempts to invoke MyInstance at the same time??

Multiple instances will be created which is violation against singleton pattern. To avoid this, let’s use lock.

namespace DesignPatternSingleton
{
    class MyFirstDesign
    {

       private MyFirstDesign() {}
        
       private static MyFirstDesign _myInstance;

       private static readonly object _lock;
       public static MyFirstDesign MyInstance()
       {
           lock(_lock)
           {
               if(_myInstance == null)
               {
                  _myInstance = new MyFirstDesign();
               }
           }
           return  _myInstance;

        }
    }

}        

At any time, only one thread enters the critical section which has lock() section. So when the next thread acquires the lock, the instance is already created so the ‘if statement’ will fail and will return the _instance.

The above program is thread safe in a multi-threaded environment.

Program.cs

using System;
using DesignPatternSingleton

Thread t1 = new Thread(() =>
{
    var tInstance = MyFirstDesign.MyInstance();
}
);

Thread t2 = new Thread(() =>
{
    var tInstance = MyFirstDesign.MyInstance();
}
);

t1.Start();
t2.Start();

t1.Join();
t2.Join();        

When the first thread is created, the tInstance holds id 1. When the second thread is created, the tInstance still holds id 1 because the ‘if statement’ will not be true.

namespace DesignPatternSingleton
{
    sealed class MyFirstDesign
    {

       private MyFirstDesign() {}
       
       public int Id { get; private set;} 
       private static MyFirstDesign _myInstance;

       private static readonly object _lock;
       public static MyFirstDesign MyInstance(int id)
       {
           lock(_lock)
           {
               if(_myInstance == null)
               {
                  _myInstance = new MyFirstDesign();
                  _myInstance.Id = id;
               }
           }
           return  _myInstance;

        }
        
    }

}        

The access member of MyFirstDesign is changed to sealed. This disallows to inherit from MyFirstDesign. It ensures we have only single,e instance of the class.

#CSharp

To view or add a comment, sign in

More articles by Shirley Vijayakumar

  • Remove Nth Node from End of List

    Given the head of a linked list, remove the nth node from the end of the list and return its head. Example 1: Example…

  • Maximum Subarray Problem

    This algorithm 'Sliding Window Technique' will be used when we want to calculate the sum in a specific range of…

  • Downloading number of .xlsm/.csv files as ZIP file from server — Angular/C#

    This demonstration is for downloading the number of .xlsm/csv files as ZIP on the client side from the server.

  • Templates in C++

    Class template is a class written with the generic programming paradigm, specifying behavior in terms of type parameter…

  • 'this' pointer Usage in C++

    I was trying to access the object outside of its scope. For example, I tried to access 'st' from utility_fun() from the…

  • Storage Class in C/C++

    The storage classes are same for C & C++ except the storage class mutable is only for C++. Auto It is the default…

    1 Comment
  • Constant Pointer vs Pointer to constant

    Reading a declaration is confusing most of the time, but there are few tricks: 1. Always read it from the right hand…

  • Reference vs Raw Pointers in C++

    What is reference? A reference is an alias for an already existing variable. Once a reference is initialised to a…

  • Mutex Vs Semaphore

    Few terms to be learnt before jumping into #Mutex & #Semaphore. Don't skip or leave in the middle, you might miss the…

    2 Comments
  • Debugging a Hang Process

    Did you know that mutex can hang the system/execution if used inappropriately? If you are new to mutex concept, click…

Explore content categories