C# Threading: Mutual exclusion (via Mutex Class)

August 3, 2010 by C#   Threading  

Observe the following faulty snippet (don't use):

using System;
using System.Threading;
using System.IO;

class Program
{
    static void Main(string[] args)
    {
        for (int i = 0; i < 3; i++)
        {
            Thread thread = new Thread(new ThreadStart(ThreadMain));
            thread.Name = String.Concat("Thread - ", i);
            thread.Start();
        }
    }

    static void ThreadMain()
    {
        // Simulate Some work
        Thread.Sleep(500);

        // Access a shared resource / critical section
        WriteToFile();
    }

    static void WriteToFile()
    {
        String ThreadName = Thread.CurrentThread.Name;
        Console.WriteLine("{0} using resource", ThreadName);

        try
        {
            using (StreamWriter sw = new StreamWriter("1.txt", true))
            {
                sw.WriteLine(ThreadName);
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.Message);
        }
    }
}

What we've got here is three threads trying to write to a file, which fails horribly since we cant concurrently write to the same file.



We need some kind of synchronization mechanism to ensure that our threads access shared resources when appropriate.

In the .NET framework one of the solutions is to use the Mutex ("Mutual exclusion") class to aid us with this issue.

In the following snippet the issue gets resolved by adding a Mutex instance to it:

static Mutex mutex = new Mutex();

static void WriteToFile()
{
	mutex.WaitOne();

	String ThreadName = Thread.CurrentThread.Name;
	Console.WriteLine("{0} using resource", ThreadName);

	try
	{
		using (StreamWriter sw = new StreamWriter("1.txt", true))
		{
			sw.WriteLine(ThreadName);
		}
	}
	catch (Exception ex)
	{
		Console.WriteLine(ex.Message);
	}

	Console.WriteLine("{0} releasing resource", ThreadName);

	mutex.ReleaseMutex();
}

The first thread that reaches the critical section (writing of the file) takes ownership of the mutex - the other threads simply wait for the mutex to be released by the thread that owns it - each taking ownership once its released etc etc etc.

Basically its like making a queue behind a resource and only one thread is allowed to use the resource at a time.



We do however get a more lightweight class in the .NET framework that provides mutual-exclusion as well, namely the Monitor class (or lock statement).

What makes the Mutex class different (and more powerful) can be observed in the following snippet:

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        bool createdNew;

        using (Mutex mutex = new Mutex(true, "App", out createdNew))
        {
            if (!createdNew)
            {
                Console.WriteLine("Application already open");
                return;
            }

            Console.WriteLine("Press any key to continue...");
            Console.ReadKey();
        }
    }
}

Mutexes can be accessed system wide and across app domains & terminals, in the preceding snippet we prevent an user of opening multiple instances of our process.

There are two types of Mutexes, local(unnamed) - which is only available within its parent process (like the first snippet) and global(named) which is available system wide (like in the last snippet).

Additionally we can set the visibility of a global(named) mutex with regards to Terminal Services. If our named mutex starts with "Global\", it becomes visible to all terminal sessions, if it starts with "Local\" its only available to the terminal session that created it.

Additional reading:
C# Threading: Mutual exclusion (via Monitor Class)
http://msdn.microsoft.com/en-us/library/system.threading.mutex.aspx


Leave a Comment


Mutex abandoned prematurely January 14, 2011 by Christoff Truter

An abandoned mutex indicates a serious programming error. http://msdn.microsoft.com/en-us/library/system.threading.abandonedmutexexception.aspx Basically - you're required to explicitly release your mutex before the process that owns the mutex terminates - else it will result in an abandoned mutex exception. Which indicates that the process that owned the mutex might have prematurely ended - crashed etc. (or it was never released in code - but hey .net can't know for sure - so it assumes that something probably went wrong)

Mutex January 14, 2011 by Vijay Bhaskar Semwal

The wait completed due to an abandoned mutex------- as i release the ownership of mutex by mutex.release(); i want to CREATE new mutex to run another process i wait for mutex ownership by mutex.waitone() but i m getting problem at mutex.waitone() The wait completed due to an abandoned mutex