Mutex vs Semaphore vs Monitor vs SemaphoreSlim using example

 

Introduction

Hello Friends..! In this article document we will understand how to work on multi-thread environment using mutex, semaphore, monitor and semaphoreslim. Before reading this article I strongly suggest you to read our previous c-sharp articles on threading and types of threading and thread pooling. For more information threading click here and for thread pooling see here.

Before we talk about mutex, semaphore, monitor and semaphoreslim and their differences let's understand what is thread safety.

What is Thread Safe in C#

If an object behaves abnormally in a multi-threaded environment then that thread is not thread safe. For example : Let's say if we run a divide function with random numbers in a multi-threaded environment since it is running in a multi-threaded environment there could be possibility that two threads are executing divide calculation same time using random numbers can create system.dividebyzeroexception error. If these types of errors occurs in a multi-thread environment that means thread is not thread safe. So it means we should take some precaution while working in a multi-threaded environment atleast those lines of code where we feel code can behave abnormally. The precaution or thread safety can be achieved using proper thread synchronization techniques. Currently available thread synchronization techniques in c-sharp are Lock/Monitor, Mutex, Semaphore and SemaphoreSlim.

Lock vs Monitor

Lock keyword is very important in multithreading. It ensures thread safety and in a multithreading environment it ensures only one thread to be executed in given moment of time. In simple words whatever code is enclosed in lock scope only one thread can enter in that lock scope and other threads have to wait till entered thread completes its work/ executes its work.

C# Lock Example

Here in this example we will first execute a simple console application divide function in a multi-thread environment without thread safety to check the output exception error. We will take up the same example as we explained in the thread safety section.

 

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

namespace ConsoleApplication1
{
    class Program
    {
        static int num1 = 0;
        static int num2 = 0;
        static Random random = new Random();
        static void Main(string[] args)
        {

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

            Divide();
        }

        static void Divide()
        {
            
            for (int i = 0; i <= 5000; i++)
            {

                try
                {
                    //Choosing random numbers between 1 to 5
                    num1 = random.Next(1, 5);
                    num2 = random.Next(1, 5);


                    //Dividing
                    double ans = num1 / num2;


                    //Reset Variables
                    num1 = 0;
                    num2 = 0;
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString());
                }
            }
        }
    }
}

Above code example is a simple console application example which executes Divide function in a multi-threaded way. Divide method loops 5000 times and takes two random numbers between 1 to 5 and divides themselves. When we ran this program we got the following error i.e. System.DividebyZeroException this because the method Divide is running in a multi-thread process i.e. static void main is the Main thread or Parent thread and inside that we have created one more thread object i.e. child thread.

So while running this program there could be possibility that while one thread is dividing other thread may be resetting the value to 0. Because of that it has created an DividebyZeroException error.

This is what we were talking about in the thread safety that is abnormal behave of an object in multithreading. To resolve this we can use any thread synchronization techniques but here as per situation best approach to use LOCK/Monitor.

To apply lock we need to use "LOCK" keyword as shown in below snippet of code.

 
static readonly object _object = new object();

lock (_object)
{
         //Choosing random numbers between 1 to 5
         num1 = random.Next(1, 5);
         num2 = random.Next(1, 5);

         //Dividing
         double ans = num1 / num2;

         //Reset Variables
         num1 = 0;
         num2 = 0;
}

Monitor in c# example

Lock keyword is just a shot-form of Monitor. So usage of monitor class or lock is one and same. But here we will also show you same code example using Monitor class. Its pretty simple whatever code you want to protect at starting point say "Monitor.Enter" and at ending point say "Monitor.Exit" as shown in below code.

 

Monitor.Enter(_object);

  //Choosing random numbers between 1 to 5
         num1 = random.Next(1, 5);
         num2 = random.Next(1, 5);

         //Dividing
         double ans = num1 / num2;

         //Reset Variables
         num1 = 0;
         num2 = 0;

Monitor.Exit(_object);

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

Lock vs Mutex

Locks/Monitors ensures the thread safety which are in process that is threads which are generated by an application (Internal threads) it does not have any control over the threads which are coming from outside of an application. Locks/Monitors provides safety againts the threads generated by an application.

Mutex ensures the thread safety which are out process that is threads which coming from outside of an application (External threads). Mutex provides safety againts the external threads.

In a multiple instance of an application external threads are created so to ensure thread safety from an external threads we need to apply mutex. Let's see a simple example how to ensure thread safety from external threads.

Mutex example in C#

 

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

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

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

            Console.ReadLine();
        }

        static bool IsInstance()
        {

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

In the above code we have created a boolean function called "IsInstance" which checks whether any other instance is running or not and that we have achieved using "WaitOne" boolean function which blocks the current thread unit waithandle receives the signal. Here in our demonstration WaitOne waits for 5 secs to receive signal from waithandle if no signal received till 5 secs it will automatically return false. If its a new thread then automatically returns true.

To see the real time scenario follow these steps.

First build the complete source code

Second Go to application containing folder

Third EXE will be generated in the BIN folder so open BIN folder.

Fourth Click on that exe and create external threads.

Fifth Do not close that previous one exe.

Sixth By keeping that previous command line exe click on the same exe file to open another new command line exe.

Seventh Keep both command line exe and open more 2 or 3 times open new command line exe.

Output

First opened command line will display message as : New Instance created

All other opened command line will display messages as : Instance already acquired

Conclusion : It is been concluded that Mutex helps us to identify whether an application is acquired by an external thread or not.

Mutex vs Semaphore

Mutex helps us to identify whether an application is acquired by an external thread or not and It allows only one single thread to enter to execute a particular task. It means mutex allows only one single external thread to enter and execute its task and same ensuring thread safety.

Semaphore you can call its an advance version of mutex with additional features. Semaphore is also helps us to work with external threads and identifying whether an application is acquired by an external thread or not. But unlike mutex Semaphore allows one or more threads to enter to executes their task with thread safety. Best feature of semaphore that we can limit those number of threads to enter.

Semaphore example in c#

Let's see a simple example of using semaphore in c#.

 

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

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

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

            Console.ReadLine();
        }

        static bool IsInstance()
        {

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

As you saw in our above code we have created a semaphore object "s1" limit of 2 threads with a name "SemaphoreQuestpond".

Now we will examine above example whether semaphore allows us to pass two external threads at a same time keeping thread safety.

First build the complete source code

Go to bin folder and click on exe file twice

Without closing both command file exe file click on exe file again

Output

First two opened command line will display message as : New Instance created

All other opened command line will display messages as : Instance already acquired

Conclusion : It is been concluded that semaphore helps us to identify whether an application is acquired by an external thread or not and at a same time allows to pass multiple threads (Limit) and keeps thread safety.

Monitor vs SemaphoreSlim

Lock is just short form of monitor. Monitor ensures thread safety with internal threads whatever code is enclosed between monitor enter and monitor exit only one thread can pass and executes its task.

SemaphoreSlim is an advance version of Monitor. SemaphoreSlim ensures the thread safety with internal threads but between scope of SemaphoreSlim it allows us to pass one or more threads to pass and executes their task. SemaphoreSlim also provides you an advance limit where you can limit the number of threads for an execution.

Watch Mutex, Semaphore and SemaphoreSlim Tutorial Video By Questpond

Hey friends..! This is all about mutex, semaphore, semaphoreslim and monitor/lock. If you folks have any doubt or query kindly drop a mail or let me know your thoughts via comment section.

If you found this article helpful. Kindly share it with your friends.

 

 

:: SHARE THIS POST ::

        
 

More C# Articles To Read Next:

 
Oct
18
2014

Thread Pooling in C#.NET with real time example - Onlinebuff

CLICK TO READ FULL ARTICLE

Views - 16752 |Category - C#

Oct
06
2014

Step by Step Partial Classes and Partial Methods in C#.NET with example

CLICK TO READ FULL ARTICLE

Views - 9174 |Category - C#

Sep
16
2014

Understand threading and types of threading in c# using an example

CLICK TO READ FULL ARTICLE

Views - 15288 |Category - C#

Aug
24
2014

Understand difference between Early Binding and Late Binding with an example in C#

CLICK TO READ FULL ARTICLE

Views - 24084 |Category - C#

Aug
10
2014

Complete Tutorial on C# 3.0 VAR Keyword with example

CLICK TO READ FULL ARTICLE

Views - 6856 |Category - C#

 
Author: Gurunatha Dogi
is a software engineer by profession and founder of Onlinebuff.com, Onlinebuff is a tech blog which covers topics on .NET Fundamentals, Csharp, Asp.Net, PHP, MYSQL, SQL Server, Cell Phones and lots more. Follow me @ and twitter.
Leave a Comment......

All fields marked with * are mandatory

o725s

 

 
Comments

Posted by Amit on 2016-04-21

If there is a lock then why to use Monitor. And if we talk about synchronization, then why someone would prefer to allow more than two threads into critical section which does by semaphore.

Posted by Glenn Aitchison on 2016-01-16

Very useful information - I know understand Mutex, Semaphore, and SemaphoreSlim

Posted by Kw on 2015-03-16

SemaphoreSlim also allows cancellation.