22.9 Using Mutexes to Synchronize Multiple Objects, Avoiding Deadlocks

 <  Day Day Up  >  

22.9 Using Mutexes to Synchronize Multiple Objects, Avoiding Deadlocks

You want to synchronize access to several variables without using nested lock statements so that you avoid the possibility of deadlocks.


Technique

The technique for synchronizing access to multiple variables at the same time involves using a Mutex . In general, a Mutex provides similar features to the C# lock statement, although with a less friendly syntax. To use a mutex, you must instantiate a Mutex instance:

 
 Mutex mutex = new Mutex(); 

You perform locking against this Mutex instance:

 
 mutex.WaitOne(); // protected code goes here mutex.ReleaseMutex(); 

Just as with events, you should make sure you dispose mutexes to free up their associated resources:

 
 mutex.Dispose(); 

So far, we have not achieved anything you cannot do with a lock statement.

However, one of the benefits of a mutex is that you can set up multiple mutexes and use the static WaitHandle.WaitAll() and WaitHandle.WaitAny() methods to wait for all of or any of the mutexes simultaneously .

Suppose you have two mutexes, represented by variables mutex1 and mutex2 , and you only want to enter a protected block of code if both those mutexes are free. You use the following code.

First come the declarations of the mutexes:

 
 Mutex mutex1 = new Mutex(); Mutex mutex2 = new Mutex(); 

Then you have the protected code block:

 
 WaitHandle [] mutexArray = new WaitHandle [] {mutex1, mutex2}; WaitHandle.WaitAll(mutexArray); // protected code mutex1.ReleaseMutex(); mutex2.ReleaseMutex(); 

WaitHandle.WaitAll() takes an array of WaitHandle objects and blocks the thread until all those objects are simultaneously free. The method does not lock any of the objects until it is in a position to be able to lock them all simultaneously ”thus eliminating the risk of this particular call causing a deadlock involving those objects. Note that, although we used mutexes here, there is no problem with using the WaitAll() method to synchronize against an array containing any other objects derived from WaitHandle .

Comments

It's worth pointing out the existence of another static method, WaitHandle.WaitAny() . This method has exactly the same syntax and effect as WaitHandle.WaitAll() except that it unblocks the thread and allows the protected code to execute as soon as any one of the objects in the array it is passed becomes free. It acquires a lock only on this one object. To enter a protected block if any one of two mutexes is free, you use the following:

 
 WaitHandle [] mutexArray = new WaitHandle [] {mutex1, mutex2}; WaitHandle.WaitAny(mutexArray); // protected code mutex1.ReleaseMutex(); mutex2.ReleaseMutex(); 

Although mutexes are more flexible than the CLR's monitor, they are less efficient because they are not implemented internally within the CLR but instead wrap native Windows kernel objects. You should always use a lock statement unless there is some reason why you need the additional flexibility offered by a mutex.

It's worth pointing out one other nice feature of WaitHandle.WaitOne() : You can pass a maximum waiting time to it:

 
 mutex.WaitOne(500, false);        // wait for 500 ms. 

The time is measured in milliseconds , or you can pass in a TimeSpan object instead. The second parameter is a bool , which is only relevant when you are dealing with remoting and contexts, so we ignore it here. The ability to set a maximum waiting time provides another reason why in some circumstances, you might prefer to use a mutex rather than a lock statement. If you do set a waiting time, then WaitOne() returns true if the lock is successfully acquired and false if the wait times out. Hence, you should use this overload like this:

 
 if (mutex.WaitOne(500, false)) {         // protected code } else {         // error-handling code for when lock has not been acquired } 

WaitHandle.WaitAll() and WaitHandle.WaitAny() have similar overloads that work in the same manner.

 <  Day Day Up  >  


Microsoft Visual C# .Net 2003
Microsoft Visual C *. NET 2003 development skills Daquan
ISBN: 7508427505
EAN: 2147483647
Year: 2003
Pages: 440

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net