Thread Safe in C# step by step

Introduction

Hey friends, one of our subscriber on #Questpond ask a very interesting question on C# Thread Safety in a multi-thread environment. To answer that question we have made this article on Thread Safety in C# step by step. This article not only will help our subscriber to understand but also to you as a reader. If you guys new to threading then we have our two articles which explains everything to know about threading, Article 1 : Threading and Types of threading., Article 2 : Thread Pooling in C#. Just go through this simple articles which will help to understand C# Threading.

#Questpond : An e-learning firm since 2002 started by Mr.ShivPrasad Koirala with an initiative to spread IT knowledge. To know more about Trainings and DVD videos and other free source materials feel free to contact us via Online Chat / Email / Phone / Social Account .

To know more about our style of training and teaching you can watch our free video learn csharp in 100 hours .

Thread Safe

To control abnormal behaviour of an object in a multi-threaded environment is called as Thread Safety. Now you must be wondering what is an abnormal behaviour of an object, Let's say we are executing a Division function which has got integer variables and values are assigned by random numbers, Dividing two variables and again resetting their values to 0. Now suppose since we are running this function in a multi-thread environment it could be possible that one thread is dividing and another thread is resetting the value to 0, during this process what happens two thread entered and attacked the variables, variable behaviour is un-controlable, it is possible that it will create a dividebyzeroexception error. If its create an error then that means thread is not safe. So friends this just an example to make you understand why it is necessary to make thread as Thread Safe in Csharp.

In order to make a thread as thread safe there are some thread synchronization techniques like Monitor/Lock, Mutex, Semaphore and SemaphoreSlim using these techniques we can achieve Thread Safety.

So Let's understand these techniques one by one.

Monitor / Lock

Lock or Monitor is one and same it works with internal threads generated by an application. Lock or monitor does not have control over external threads. In a multi-thread environment it ensures that only one thread to be executed in given moment of time and other threads have to wait till entered thread completes its work/ executes its work.

We will take up a simple example as explained above also, a divide function which will run on multi-thread environment and possible it might occur a divide by zero exception error.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;

 class Program
    {
        static int a = 0;
        static int b = 0;
        static Random random = new Random();
        
        static void Main(string[] args)
        {

            Thread obj = new Thread(Division);
            obj.Start();

            Division();
        }

        static void Division()
        {

            for (int i = 0; i <= 500; i++)
            {

                try
                {
                   
                        //Choosing random numbers between 1 to 5
                        a = random.Next(1, 10);
                        b = random.Next(1, 10);


                        //Dividing
                        double ans = a / b;


                        //Reset Variables
                        a = 0;
                        b = 0;

                        Console.WriteLine("Answer : {0} --> {1}", i, ans);
                    
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
    

As you saw in above code that we have created an example which we have discussed in above (thread Safe) part. This example we have generated a random numbers between 1-10 in a 500 loop =, It could be possible that divide by zero an exception will occur or might not occur, decision is very sceptical means an object can behave abnormal anytime in process of code. In order to prevent code from abnormal behaviour we will apply thread safe technique i.e. Monitor or lock to it.

So let's apply it.


class Program
    {
        static int a = 0;
        static int b = 0;
        static Random random = new Random();
        static readonly object _object = new object();
        static void Main(string[] args)
        {

            Thread obj = new Thread(Division);
            obj.Start();

            Division();
        }

        static void Division()
        {

            for (int i = 0; i <= 500; i++)
            {

                try
                {
                    Monitor.Enter(_object);
                   
                        //Choosing random numbers between 1 to 5
                        a = random.Next(1, 10);
                        b = random.Next(1, 10);


                        //Dividing
                        double ans = a / b;


                        //Reset Variables
                        a = 0;
                        b = 0;

                        Console.WriteLine("Answer : {0} --> {1}", i, ans);
                    Monitor.Exit(_object);

                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
    
    

So as you see friends MONITOR ensures thread safety and prevent code from showing abnormal results.

Mutex :

Mutex works with external threads, External threads basically coming from outside of an application.

Like Monitor, Mutex works with a single thread only. For example let's suppose you have a house for rent and once a house is rented to one tenant (House is locked), Another new tenant have to wait in a queue to get keys or until a house is vacanted.

So same way mutex allows only one thread to enter at a time and waits other threads. Other threads needs to wait in a queue till entered thread completes its work. Once entered thread finishes its work then mutex access another queued thread to enter.

On the same let's see an example.

In order to apply mutex in a class code we need to use Mutext class.

Mutex ObjMutex = new Mutex(true,"LearnCsharp");

In this example we will create a simple boolean function which will check wheather any thread acquired or not.


 

class Program
{
        static Mutex ObjMutex = new Mutex(true, "LearnCsharp");
        
        static void Main(string[] args)
        {

            if (CheckInstance() == true)
            {
                
                Console.WriteLine("New Instance created...");
            }
            else
            {

                Console.WriteLine("Instance already acquired...");
            }

            Console.ReadLine();
        }

        static bool CheckInstance()
        {

            if (ObjMutex.WaitOne(5000,false) == false)
            {
                return false;
            }
            else
            {
                return true;
            }
          
        }
}



As you saw in above code we have created an object "objMutex" and created a function "CheckInstance" which checks wheather any thread is acquired instance or not. To let's run this program.

To check output build the source code, then go to exe containing folder (Located in BIN),double click on exe file.

Once you have clicked on an EXE file a command line output will generate, now do not close this command line output just minimize it now same way open more 3 command line exe output.

Images as shown below.

As you see from the output, It is conclude that Mutex helps to identify an application is acquired by an external thread or not.

Semaphore

Semaphore is just an advance version of Mutex , It also helps to identify an application is acquired by an external thread or not. Instead of one thread to process work, Semaphore allows one or more threads to enter a same moment of time to process work with thread safety. In semaphore we have a feature to limit those no of threads to enter.

Now let's see an example of semaphore.



class Program
{
  
    static Semaphore objSem = new Semaphore(2, 2, "LearnCsharp");
    
    static void Main(string[] args)
    {

        if (CheckInstance() == true)
        {
            
            Console.WriteLine("New Instance created...");
        }
        else
        {

            Console.WriteLine("Instance already acquired...");
        }

        Console.ReadLine();
    }

    static bool CheckInstance()
    {

        if (objSem.WaitOne(5000, false) == false)
        {
            return false;
        }
        else
        {
            return true;
        }
      
    }
}

Output

As you saw we have created a semaphore object "objSem" with a limit of 2 threads with a name called "LearnCsharp".

Now we will check above code whether semaphore give rights to pass 2 external threads at a same time keeping thread safety.

So follow same steps as we did it for Mutex above, i.e. go to bin folder and open up three command line together.

As you saw it is concluded that semaphore allowed 2 threads simultaneously to process work and queued 3rd thread.

SemaphoreSlim

SemaphoreSlim is just an advance version of Monitor. As like monitor, SemaphoreSlim allows you work with internal threads but instead of single thread it allows to pass one or more threads in a given moment of time. In this advance version you can limit no of threads for an execution.

We have not created a code sample for this because it will be like home work readers to create a test script and mail us. This will help us to know that how much you are understanding through our articles.

So hey friends hope you like our article on thread safety. Share it on your social account to spread C# knowledge. Next time we soon come up with a new article.

+91-22-66752917
+91 9967590707
questpond@questpond.com / questpond@yahoo.com