Reader Level:
ARTICLE

Threading with Mutex

Posted by Akshay Teotia Articles | Multithreading in C# December 05, 2011
A mutual exclusion (“Mutex”) is a mechanism that acts as a flag to prevent two threads from performing one or more actions simultaneously.
  • 0
  • 0
  • 48650

A Mutex is like a C# lock, but it can work across multiple processes. In other words, Mutex can be computer-wide as well as application-wide.

A Mutex is a synchronization primitive that can also be used for interprocess synchronization. When two or more threads need to access a shared resource at the same time, the system needs a synchronization mechanism to ensure that only one thread at a time uses the resource. Mutex is a synchronization primitive that grants exclusive access to the shared resource to only one thread. If a thread acquires a Mutex, the second thread that wants to acquire that Mutex is suspended until the first thread releases the Mutex.

In short, A mutual exclusion ("Mutex") is a mechanism that acts as a flag to prevent two threads from performing one or more actions simultaneously. The entire action that you want to run exclusively is called a critical section or protected section.

A critical section is a piece of code that accesses a shared resource (data structure or device) but the condition is that only one thread can enter in this section at a time.

Modern programming languages support this natively. In C#, it's as simple as:

  • Instantiating a new static Mutex object that's accessible from each thread.
  • Wrapping whatever code you want to be executed in the critical section with that object's WaitOne() and ReleaseMutex() methods in each thread

With a Mutex class, you call the WaitHandle.WaitOne method to lock and ReleaseMutex to unlock. Closing or disposing a Mutex automatically releases it. Just as with the lock statement, a Mutex can be released only from the same thread that obtained it.

This example shows how a local Mutex object is used to synchronize access to a protected resource.

using System;
using System.Collections;
using System.Threading;
namespace Mutexclass
{
class Akshay
    {
        private static Mutex mutex = new Mutex();
        private const int numhits = 1;
        private const int numThreads = 4;
        private static void ThreadProcess()
        {
            for (int i = 0; i < numhits; i++)
            {
                UseCsharpcorner();
            }
        }
        private static void UseCsharpcorner()
        {
            mutex.WaitOne();   // Wait until it is safe to enter.
            Console.WriteLine("{0} has entered in the C_sharpcorner.com",
                Thread.CurrentThread.Name);
            // Place code to access non-reentrant resources here.
           Thread.Sleep(500);    // Wait until it is safe to enter.
            Console.WriteLine("{0} is leaving the C_sharpcorner.com\r\n",
                Thread.CurrentThread.Name);
            mutex.ReleaseMutex();    // Release the Mutex.
        }
       static
void Main(string[] args)
       {
             for (int i = 0; i < numThreads; i++)
            {
                Thread mycorner = new Thread(new ThreadStart(ThreadProcess));
                mycorner.Name = String.Format("Thread{0}", i + 1);
                mycorner.Start();
            }
            Console.Read();
        }
    }
}

Output

shres.gif

Use a Mutex to control a shared resource against two current threads

using System;
using System.Threading;
class MyCounter
{
    public static int count = 0;
    public static Mutex MuTexLock = new Mutex();
}
class IncThread
{
    public Thread th;
    public IncThread()
    {
        th = new Thread(this.GO);
        th.Start();
    }
    void Go()
    {
        Console.WriteLine("IncThread is waiting for the mutex.");
        MyCounter.MuTexLock.WaitOne();
        Console.WriteLine("IncThread acquires the mutex.");
        int num = 10;
        do
        {
            Thread.Sleep(50);
            MyCounter.count++;
            Console.WriteLine("In IncThread, MyCounter.count is " + MyCounter.count);
            num--;
        } while (num > 0);
        Console.WriteLine("IncThread releases the mutex.");
        MyCounter.MuTexLock.ReleaseMutex();
    }
}
class DecThread
{
    public Thread th;
    public DecThread()
    {
        th = new Thread(new ThreadStart(this.Go));
        th.Start();
    }|
   void Go()
|    {
        Console.WriteLine("DecThread is waiting for the mutex.");
        MyCounter.MuTexLock.WaitOne();
        Console.WriteLine("DecThread acquires the mutex.");
        int num = 10;
        do
        {
            Thread.Sleep(50);
            MyCounter.count--;
            Console.WriteLine("In DecThread, MyCounter.count is " + MyCounter.count);
            num--;
        } while (num > 0);
        Console.WriteLine("DecThread releases the mutex.");
        MyCounter.MuTexLock.ReleaseMutex();
    }
}
class MainClass
{
    public static void Main()
    {|
        IncThread myt1 = new IncThread();
        DecThread myt2 = new DecThread();
        myt1.thrd.Join();
        myt2.thrd.Join();
        Console.Read();
    }
}

Output

2.gif

Use the Mutex object: WaitOne

An overloaded WaitOne() method also accepts a TimeSpan object, useful if the thread should wait only until a period of time has lapsed. Typically this is employed when there's a risk ofdeadlock, where two or more threads are waiting for the same Mutex to become available simultaneously. Deadlock is as bad as it sounds, since it can result in an application that has "stalled out" for all intents and purposes.

using System;
using System.Threading;
namespace waitonmethod
{
class Akshay
    {
        private static int Runs = 0;
        static Mutex mutex = new Mutex(false, "RunsMutex");|
        public static void CountUp()
        {
            while (Runs < 10)
            {
                // acquire the mutex
                mutex.WaitOne();
                int Temp = Runs;
                Temp++;
                Console.WriteLine(Thread.CurrentThread.Name + " " + Temp);
                Thread.Sleep(800);
                Runs = Temp;
                // release the mutex
                mutex.ReleaseMutex();
            }
        }
        public static void Main()
        {
            Thread t2 = new Thread(new ThreadStart(CountUp));
            t2.Name = "t2";
            Thread t3 = new Thread(new ThreadStart(CountUp));
            t3.Name = "t3";
            t2.Start();
            t3.Start();
            Console.Read();
        }
    }
}

Output

3.gif

Own a Mutex

A Mutex object can be owned by a thread. When owned, it can only be owned by one single thread. When it is owned by a thread, other threads cannot own it until the original thread owner releases it. A thread which wants to own a Mutex calls the Mutex instance's WaitOne() method. An owning thread which wants to release the Mutex calls the ReleaseMutex() method.

using System;|
using System.Threading;
namespace ownamutex
{
 class Akshay
    {
        public static void Main()
        {
           bool ownsMutex;
             using (Mutex mutex = new Mutex(true, "MutexExample", out ownsMutex))
            {
                if (ownsMutex)
                {
                    Console.WriteLine("Owned");
                    mutex.ReleaseMutex();
                }
                else
                {
                   Console.WriteLine("Another instance of this application " +" already owns the mutex named MutexExample.");
                }
            }
            Console.Read();
        }
    }
}

Output

4.gif

Name a Mutex

A Mutex can be either named or unnamed. If a Mutex is named, it is eligible to be a system-wide Mutex that can be accessed from multiple processes. If a Mutex is unnamed, it is an anonymous Mutex which can only be accessed within the process in which it is created.

using System;
using System.Threading;
namespace Namingthread
{
    class Akshay
    { 
        public static void Main(string[] args)
        {
            string mutexName = "akshay";
            Mutex m = new Mutex(false, mutexName);
            for (; ; )
            {
                m.WaitOne();
                Console.WriteLine("Have Mutex");
                Console.WriteLine("Releasing");
                m.ReleaseMutex();
            }
            Console.Read();
        }
   }
}

output

5.gif

COMMENT USING