[Previous] [Contents] [Next]

Synchronizing Code by Using the Mutex Class

The Mutex class-defined in the System.Threading namespace-is a run-time representation of the Win32 system primitive of the same name. You can use a mutex to serialize access to code as you can use a monitor lock, but mutexes are much slower because of their increased flexibility. The term mutex comes from mutually exclusive, and just as only one thread at a time can obtain a monitor lock for a given object, only one thread at a time can obtain a given mutex.

You can create a mutex in C# with the following three constructors: -

Mutex( )
Mutex(bool initiallyOwned)
Mutex(bool initiallyOwned, string mutexName)

The first constructor creates a mutex with no name and makes the current thread the owner of that mutex. Therefore, the mutex is locked by the current thread. The second constructor takes only a Boolean flag that designates whether the thread creating the mutex wants to own it (lock it). And the third constructor allows you to specify whether the current thread owns the mutex and to specify the name of the mutex. Let's now incorporate a mutex to serialize access to the Database.SaveData method: -

using System;
using System.Threading;
class Database
{
    Mutex mutex = new Mutex(false);
    public void SaveData(string text)
    {
        mutex.WaitOne();
        Console.WriteLine("Database.SaveData - Started");
        Console.WriteLine("Database.SaveData - Working");
        for (int i = 0; i < 100; i++)
        {
            Console.Write(text);
        }
        Console.WriteLine("\nDatabase.SaveData - Ended");
        mutex.Close();
    }
}
class ThreadMutexApp
{
    public static Database db = new Database();
    public static void WorkerThreadMethod1()
    {
        Console.WriteLine("Worker thread #1 - Started");
        Console.WriteLine
            ("Worker thread #1 - Calling Database.SaveData");
        db.SaveData("x");
        Console.WriteLine("Worker thread #1 - Returned from Output");
    }
    public static void WorkerThreadMethod2()
    {
        Console.WriteLine("Worker thread #2 - Started");
        Console.WriteLine
            ("Worker thread #2 - Calling Database.SaveData");
        db.SaveData("o");
        Console.WriteLine("Worker thread #2 - Returned from Output");
    }
    public static void Main()
    {
        ThreadStart worker1 = new ThreadStart(WorkerThreadMethod1);
        ThreadStart worker2 = new ThreadStart(WorkerThreadMethod2);
        Console.WriteLine("Main - Creating worker threads");
        Thread t1 = new Thread(worker1);
        Thread t2 = new Thread(worker2);
        t1.Start();
        t2.Start();
    }
}

Now, the Database class defines a Mutex field. We don't want the thread to own the mutex just yet because we'd have no way of getting into the SaveData method. The first line of the SaveData method shows you how you need to attempt to acquire the mutex-with the Mutex.WaitOne method. At the end of the method is a call to the Close method, which releases the mutex.-

The WaitOne method is also overloaded to provide more flexibility in terms of allowing you to define how much time the thread will wait for the mutex to become available. Here are those overloads: -

WaitOne( )
WaitOne(TimeSpan time, bool exitContext)
WaitOne(int milliseconds, bool exitContext)

The basic difference between these overloads is that the first version-used in the example-will wait indefinitely, and the second and third versions will wait for the specified amount of time, expressed with either a TimeSpan value or an int value.

[Previous] [Contents] [Next]