Singleton Pattern

Singleton pattern is a simple design pattern in software practice and sometimes considered as an anti-pattern due its tight coupling nature.

A very simple non thread safe implementation of the Singleton pattern would be like this.

Singleton non thread safe

class Singleton
{
  privatestatic Singleton _instance;
  private Singleton()
  {
    Console.WriteLine(Singleton instantiated);
  }
 
publicstatic Singleton SingletonInstance
{
  get
   {
        if (_instance ==null)
            {
               // delay the object creation to demonstrate the thread saftey.
               Thread.Sleep(1500);
            _instance =new Singleton();
            }
      return     _instance;
  }
 }
}

Run the above class using Main method shown below, you can notice Singleton constructor is called twice by the both threads, since it is not thread safe. ( You can use the same Main methid implementation for all 3 Singleton implementations)

Main method implementation

class Program
{
staticvoid Main(string[] args)
{
new Thread(() => { Singleton sin1 = Singleton.SingletonInstance; }).Start();
Singleton sin2 = Singleton.SingletonInstance;
 
Console.ReadKey();
}
}

Singleton thread safe

Making the above implementation to a thread safe code is not a complex task, we can use our same old locking technique.

class Singleton
{
privatestatic Singleton _instance;
privatestaticobject _lock =newobject();
 
private Singleton()
{
Console.WriteLine(Singleton instantiated);
}
 
publicstatic Singleton SingletonInstance
{
get
{
lock (_lock)
{
if (_instance ==null)
  {
      // delay the object creation to demonstrate the thread saftey.
        Thread.Sleep(1500);
         _instance =new Singleton();
   }
return _instance;
}
}
}
}

The above is a perfect Singleton implementation in C#. But is there any other way that we can have the Singleton behavior without compensating our performance into locking. Because locking is a performance drop for sure.

Singleton C# way  – The trendy way

This is a neat and a trendy way to implement the Singleton.

We do not use locks in this implementation and it is very fast yet purely thread safe.

class Singleton
{
    privatestaticreadonly Singleton _instance;
 
    static Singleton()
    {
             _instance =new Singleton();
     }
 
    private Singleton()
   {
       Console.WriteLine(Singleton instantiated);
    }
 
   public static Singleton SingletonInstance
  {
     get
    {
      return _instance;
     }
  }
}

The magic is, static constructor.

A static constructor is used to initialize any static data, or to perform a particular action that needs to be performed once only. It is called automatically before the first instance is created or any static members are referenced.

To remeber simply you can think that the static constructor is called when the class is loaded.

More about static constructors in this MSDN article.

Sleeping Barber – C#

The sleeping barber is one of the problems which is used to demonstrate the correct thread notification mechanism. Here’s the a sample code for the sleeping barber problem in C# for .NET 4.0. Keep in mind that this code is optimized for the .NET 4.0 not for prior versions. You have concurrent collections in .NET 4.0.

 

using System;
using System.Threading;
using System.Collections.Concurrent;
using Microsoft.ConcurrencyVisualizer.Instrumentation;

namespace SleepingBarber
{
    class Program
    {
        internal static AutoResetEvent customerEvent = new AutoResetEvent(false);

        // no explict locks needed as it is a ConcurrentQueue > feature in .NET 4.0
        internal static ConcurrentQueue<Customer> queue = new ConcurrentQueue<Customer>();

        static void Main(string[] args)
        {
            Random rand = new Random();

            // make the barber background so the program can exit once the main thread is finished.
            // this does not impact the thread priority.
            new Thread(Barber.CutHair) { IsBackground = true, Name = "Barber" }.Start();

            Thread.Sleep(100);

            Thread.CurrentThread.Name = "Main";
            // creating 25 customers in random order
            for (int i = 0; i <25; i++)
            {
                // temp is used to avoid the captured variable problem
                int temp = i;
                Thread.Sleep(rand.Next(600, 2000));
                Customer c = new Customer() {Name = "Customer " + temp };
                queue.Enqueue(c);

                if (queue.Count == 1)
                {
                    Customer.WakeUpBarber();
                }
            }

            Console.ReadKey();
        }
    }

    class Customer
    {
        public string Name { get; set; }

        internal static void WakeUpBarber()
        {
            Program.customerEvent.Set();
        }
    }

    class Barber
    {
        internal static void CutHair()
        {
            while (!Program.queue.IsEmpty)
            {
                Customer c;

                // time to cut the hair is 1 sec
                Thread.Sleep(1000);

                // after cutting hair barber removes him from the queue
                if (Program.queue.TryDequeue(out c))
                {
                    Console.WriteLine("Done hair cutting to {0}", c.Name);
                }
                else
                {
                    // this will never happen in this scenario as only one barber is here
                    Console.WriteLine(" 😦 customer is not going out ...");
                }
            }

            Console.WriteLine("Going to sleep.... grr...err....");
            GoToSleep();
        }

        private static void GoToSleep()
        {
            using (Markers.EnterSpan("wait start"))
            {
                Program.customerEvent.WaitOne();
                Console.WriteLine("Waking up..Oh ! Customer arrived..");
            }
            CutHair();
        }
    }
}