Handling Deadlock in Code Using Mutex

Mutexes are not new to the .NET framework. The Win32 API supports an object called a mutex and the .NET framework Mutex class is actually a wrapper class for the same Win32 Kernel mutex object. Mutex objects are generally used to synchronize threads across process. Mutexes are namable and hence you can signal whether the Mutexis acquired or not by some other thread within a process or across processes. You should note a mutex is created with the call to Win32 CreateMutex. You can check the ownership of the Mutex using WaitAll, WaitAny and so on calls and that avoids deadlocks.

As I have already said, a mutex has an underlying Win32 Kernel object associated with it, even though it supports cross-process thread synchronization, yet it is heavier than a Monitor and you need to explicitly close the mutex when it is released.

Let's us use a mutex in code to clarify how a mutex is used.

  1. static Mutex _mlock = new Mutex();  
  2. public static long Sum()  
  3. {  
  4.     long counter = 0;  
  5.     if (_mlock.WaitOne(1000))  
  6.     {  
  7.         try  
  8.         {  
  9.             for (int i = 0; i < Repository.Count; i++)  
  10.                 Interlocked.Add(ref counter, Repository[i]);  
  11.         }  
  12.         finally  
  13.         {  
  14.             _mlock.ReleaseMutex();  
  15.         }  
  16.     }  
  17.     return counter;  
  18. }  
  19.   
  20. public static void AddToRepository(int nos)  
  21. {  
  22.     if (_mlock.WaitOne(2000))  
  23.     {  
  24.   
  25.         try  
  26.         {  
  27.             for (int i = 0; i < nos; i++)  
  28.                 Repository.Add(i);  
  29.         }  
  30.         catch { }  
  31.         finally  
  32.         {  
  33.             _mlock.ReleaseMutex();  
  34.         }  
  35.     }  
  36. }  
 
In this code, I created a mutex and a lock is acquired using the WaitOne method of the Mutex object. We have also specified the Timeout value for the Mutex. If the Timeout is elapsed then the Mutex returns false.

If you have more than one mutex that needs to be acquired before running code, you can put all the mutexes in an array and call "WaitHandle.WaitAll" to acquire all mutexes at a time.

  1. Mutex[] mutexes = { this._mlock, this._mlock2, this._mlock3};  
  2. if(WaitHandle.WaitAll(mutexes))  
  3. {  
  4.       // All mutexex acquired.  
  5. }  

The WaitHandle method actually avoids the deadlock internally.

Similar to WaitAll the WaitHandle class also supports methods like WaitAny or SignalAndWaitmethods to acquire locks.

Using a mutex for an instance count

As I have already explained, mutexes can be named and can be accessed across process. You can use a mutex to count the number of instances of a certain thread created in a specific machine. Let's see how to do this as in the following:

  1. bool instanceCountOne = false;  
  2. Mutex mutex = new Mutex(true"MyMutex"out instanceCountOne);  
  3.  using (mutex)  
  4.  {  
  5.       if (instanceCountOne)  
  6.       {  
  7.             // When there is only one Instance  
  8.        }  
  9.   }  
 
Here we name the mutex "MyMutex" that will count all the existing processes of the system and see whether the MyMutex is newly created or its already there.

The "instanceCountOne" identifies whether the name is newly created or not. Thus it will identify the instance count of the Mutex.

If you write this code at the entry point of your application, you can look at how many instances of the application actually exists in the system.

I hope this article helps you.

Thank you for reading.