How to use C# Mutex for Thread Lock Synchronization

Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn

Never miss a post!

Sign up for our newsletter and get FREE Development Trends delivered directly to your inbox.

You can unsubscribe any time. Terms & Conditions.
Categories

A mutex is a synchronized locking mechanism, which is used to synchronize multiple requests of accessing a single resource. One resource can be associated with the mutex and that resource can only release the mutex. It enforces the prevention of resources when there are many requesting threads of execution and ensures that a single thread must acquire the resource.

What is a Mutex?

In 1965, Edsger W. Dijkstra identified the requirement that the one thread of execution must not enter in its critical section when the other thread is already in its critical section because the concurrent sharing of resources can cause an erroneous process or behavior. Therefore, when the resource is occupied by one thread of execution, it must be in a protected state to avoid any unexpected behavior.

Mutex is one of the type of mutual exclusion which prevents the race conditions in a program. It is designed to enforce a concurrent control policy which makes sure that the component must follow the rules and design methodologies in order to maintain the stable state of the whole system because a failure in the policy can lead to a data corruption from the shared resources.

Mutex vs Semaphore vs Lock

Mutex

Mutex also referred as Mutual Exclusion, which states that the lockable object can only be owned by one thread at a time and only the owner thread can release the lock on a mutex. Other threads have to wait until the owner releases the process. If the multiple requests are made to acquire the lock even by the same thread, this may result in failure or blocking of that object. To own a mutex object, a thread uses WaitOne() method whereas ReleaseMutex() method is being used to release the mutex object.

Semaphore

Semaphore ensures the limit of the shared resources accessed by the threads of executions. It is a relaxed version of locks that has multiple threads and a current thread. It has two operations, i.e. wait and signal. Any thread can own the objects with a wait operation. Releasing an ownership with a signal command, is called as incrementing the semaphore and it also increments the current count. If the count was zero before giving the signal command, the thread which is in a wait state will be set as awake. If there are multiple threads that are waiting in wait state, only one thread will be set as awake and if the count reaches at maximum limit, then the signal command is ignored.

Lock

In Lock mechanism, a single thread is allowed on shared resource. If any other thread tries to enter the critical state, it will transfer into wait state until the object is released. It calls the Enter command to start the block and calls the Exit command at the end of the block code to release the occupied resource. Threads will be in wait state until the blocked object releases the lock, and the lock code will only be accessible to one thread at a time inside the code.

Examples

You can use the mutex mechanism in any of the following manner:

Single Application Instance

You can allow only a single instance of an application by using the following code:

using System;  
using System.Threading;  

namespace MyFirstMutexApp 
{  
    public class Program  
    {  
        private static Mutex objMutex = null;
        
        public static void Main(string[] args)  
        {  
            const string myAppName = "MyFirstSingleMutexApp";  
            bool isCreatedNew;  
  
            objMutex = new Mutex(true, myAppName, out isCreatedNew);  
  
            if (!isCreatedNew)  
            {  
                Console.WriteLine(myAppName + " is already running!");  
                Console.ReadKey();  
                return;  
            }  
  
            Console.WriteLine("Welcome to the " + myAppName);  
            Console.ReadKey();  
        }  
    }  
}

Use a Mutex to control a Shared Resource

If you need to access a shared resource against two current threads, you can achieve it by using the following code:


using System;  
using System.Threading;  
 
public class MySharedMutexCounter { 
  public static int count = 0; 
  public static Mutex ObjMutex = new Mutex(); 
} 
 
public class MyThreadA {    
  public Thread objThread;  
  
  public MyThreadA() {  
    objThread = new Thread(this.run);  
    objThread.Start();  
  }  
  
  public void run() {  
    Console.WriteLine("MyThreadA is waiting for the mutex."); 
    MySharedMutexCounter.ObjMutex.WaitOne(); 
    Console.WriteLine("MyThreadA acquires the mutex."); 
    
    int NumCount = 10;
    do {  
      Thread.Sleep(50);  
      MySharedMutexCounter.count++;  
      Console.WriteLine("In MyThreadA, MySharedMutexCounter.count is " + MySharedMutexCounter.count);  
      NumCount--; 
    } while(NumCount > 0);  
  
    Console.WriteLine("MyThreadA releases the mutex.");   
 
    MySharedMutexCounter.ObjMutex.ReleaseMutex(); 
  }  
}  
 
public class MyThreadB {  
  public Thread objThread;  
  
  public MyThreadB() {  
    objThread = new Thread(new ThreadStart(this.run));  
    objThread.Start();  
  }  
  
  public void run() {  
    Console.WriteLine("MyThreadB is waiting for the mutex."); 
    MySharedMutexCounter.ObjMutex.WaitOne(); 
    Console.WriteLine("MyThreadB acquires the mutex."); 
 
    int NumCount = 10;
    do {  
      Thread.Sleep(50);  
      MySharedMutexCounter.count--;  
      Console.WriteLine("In MyThreadB, MySharedMutexCounter.count is " + MySharedMutexCounter.count);  
      NumCount--; 
    } while(NumCount > 0);  
  
    Console.WriteLine("MyThreadB releases the mutex.");  
 
    MySharedMutexCounter.ObjMutex.ReleaseMutex(); 
  }  
}  
  
public class MainClass {  
  public static void Main() {  
    MyThreadA mtA= new MyThreadA();  
    MyThreadB mtB = new MyThreadB();  
  
    mtA.objThread.Join(); 
    mtB.objThread.Join(); 
  }  
}

Using the WaitOne overloaded method

You can use WaitOne() method to make the thread wait for a certain period of time.

using System;  
using System.Threading;  

namespace MyFirstMutexApp 
{  
   public class SampleClass  
   {
      public static void Main()
      {
           // Create a unique name mutex as this is available 
           using (var mutex = new Mutex(false, "MyFirstMutexSingletonApp"))
           {
               // Check signal state of the mutex and exit without creating a deadlock
               bool isApplicationAlreadyRunning = !mutex.WaitOne(TimeSpan.Zero);
               if (isApplicationAlreadyRunning)
               {
                   Console.WriteLine("Sorry! Application is already running.");
                   return;
               }
               // Continue if it’s not running already 
               Console.WriteLine("Hello World!");
               Console.ReadKey();
               mutex.ReleaseMutex();
           }
        }
     }  
}  

Names vs Unamed Mutex

Mutex can be named and unnamed depending on the requirement. If you wish to have mutex to be accessed system wide, then a proper and unique name must be given, but if you wish to limit access to the process only from where it is created, then there is no need to provide a name.

using System;  
using System.Threading;  

namespace MyFirstMutexApp 
{  
    public class SampleClass  
    {   
        public static void Main(string[] args)  
        {  
            string namedMutex = "MyNamedMutex";  
            Mutex mutex = new Mutex(false, namedMutex);  
            for (; ; )  
            {  
                m.WaitOne();  
                Console.WriteLine("Have Mutex");  
                Console.WriteLine("Releasing");  
                m.ReleaseMutex();  
            }  
            Console.Read();  
        }  
   }  
}  
Share on facebook
Facebook
Share on twitter
Twitter
Share on linkedin
LinkedIn

Our website uses cookies that help it to function, allow us to analyze how you interact with it, and help us to improve its performance. By using our website you agree by our Terms and Conditions and Privacy Policy.