Tuesday, 14 January 2014

Protecting shared state with Mutex in C#.

In this post, we are going to have a look at how to protect shared state with a Mutex Object. But before I begin,  a good description of what a mutex should be in order. First of all the name mutex was coined from the phrase "Mutual exclusion". So from this phrase we can see that a mutex object is used to protect "shared state" and ensure exclusive execution of the state by one thread at a time.  A mutex functions just like the Monitor class used by the lock keyword but with a very subtle difference. The main difference is that mutex is a low level object implemented by Operating system whereas the Monitor class is a managed object and that it is used by the OS to synchronize access of a shared resources between more than one process.

The mutex class resides in the System.Threading namespace. It has about five constructors that takes various parameters during initialization. But out of the five, the parameterless , the one parameter and two parameters constructors are the most common ones. Your choice of constructor for initialization depends on the domain and scenario you area working on. 

If you are not interested in inter-process synchronization and you don't care much which threads first gain access to the protected block of code then the constructor with the parameterless constructor is the way to go. So to initialize a mutex class, you will write the code as shown below:

                                          Mutex myCodeLocker =  new Mutex();

If you want to initialize a mutex object, but you also want the thread that initialized the object to be the first to gain access to the protected state and you are only interested in the within process synchronization then the constructor with one parameter is the way  to go. In this constructor, you will pass a boolean argument (in this case true) indicating your interest. Because false is the default value for this parameter, always make sure you pass the correct boolean value when using this constructor.

                                         Mutex myCodeLocker = new Mutex(true);


In this last scenario, if you want the mutex object to be visible to other processes in the system, then you will have to name the mutex. This is done by passing the name as a second argument to the constructor. It is this name that will be used by other processes to access this mutex.

                            Mutex myCodeLocker = new Mutex(false, "BluetoothAccessLocker");

Notice that in the above piece of code that I passed false as the first argument. This is to show you that it's not a must that a mutex whose visibility is beyond one proccess should be owned by the starting thread. Also for another process to access this lock object, it  must provide the name which was given to the mutex. To clarify, I believe an example is in order.

public static Mutex GetMutex(string mutexName)
{   
     Mutex requiredMutex;
      
            if(Mutex.TryOpenExisting(mutexName, out requiredMutex))
           {
                     return requiredMutex;
            }
       return new Mutex(false, mutexName);
 }


The above method GetMutex() takes the name of the mutex to get and tries to open and return the mutex else it will create a new Mutex and return it to the caller.

WaitOne and ReleaseMutex() instance methods.

The two most common instance methods used in the mutex class is WaitOne() and ReleaseMutex(). The WaitOne() method tries to acquire lock on a piece of code. It succeeds if no thread has already acquired the lock on the mutual exclusive code, otherwise it blocks the current thread until the thread that acquired the lock releases the lock with ReleaseMutex(). To clarify, lets make use of an example.

var myCodeLocker = GetMutex("BluetoothAccessLocker");

myCodeLocker.WaitOne();
/*
Code statements that locks is being acquired on
*/
myCodeLocker.ReleaseMutex();

In the above code snippet, if there is no other thread currently executing this piece of code, then the current thread will succeed in gaining access otherwise it will block and wait until the locker thread releases the lock. To view more examples on how to use these methods, I advice taking a look at this post

There are various overloads for the WaitOne() that takes Integer/TimeSpan value. It is typically used in a situationwhere deadlock may become an issue so as to break out of the blocking state when the given time exhausts. Happy coding.






No comments:

Post a Comment