.NET Synchronization Support

 < Day Day Up > 



The .NET Framework provides a few classes in the System.Threading, System.EnterpriseServices, and System.Runtime.Compiler namespaces that allow the programmer to develop thread-safe code. The table below briefly describes some of the synchronization classes in the .NET Framework.

Class

Description

Monitor

Monitor objects are used to lock the critical sections of code so that one and only one thread has access to those critical sections at any point of time. They help ensure the atomicity of critical sections of code.

Mutex

Mutex objects are similar to Monitor objects with the exception that they grant exclusive access to a resource shared across processes to only one thread. The Mutex overloaded constructor can be used to specify Mutex ownership and name.

AutoResetEvent, ManualResetEvent

AutoResetEvent and ManualResetEvent are used to notify one or more waiting threads that an event has occurred. Both these classes are NotInheritable.

Interlocked

The Interlocked class has the CompareExchange(), Decrement(), Exchange(), and Increment() methods that provide a simple mechanism for synchronizing access to a variable that is shared by multiple threads.

SynchronizationAttribute

SynchronizationAttribute ensures that only one thread at a time can access an object. This synchronization process is automatic and does not need any kind of explicit locking of critical sections.

MethodImplAttribute

This attribute notifies the compiler on how the method should be implemented.

The MethodImplAttribute Class

The System.Runtime.CompilerServices namespace, as its name suggests, contains attributes that affect the runtime behaviour of the CLR (Common Language Runtime). MethodImplAttribute is one such attribute that notifies the CLR on how the method is implemented. One of the MethodImplAttribute constructors accepts the MethodImplOptions enumeration as a parameter. The MethodImplOptions enumeration has a field named Synchronized that specifies that only one thread is allowed to access this method at any point of time. This is similar to the lock keyword that we used in the previous example. The listing below of MI.cs shows how you can use this attribute to synchronize a method:

    using System;    using System.Runtime.CompilerServices;    using System.Threading;    namespace MethodImpl    {      class MI      {        //This attribute locks the method for use        //by one and only one thread at a time.        [MethodImpl(MethodImplOptions.Synchronized)]        public void doSomeWorkSync()        {          Console.WriteLine("doSomeWorkSync()" +                            "--Lock held by Thread " +                            Thread.CurrentThread.GetHashCode());          //When a thread sleeps, it still holds the lock          Thread.Sleep(5 * 1000);          Console.WriteLine("doSomeWorkSync()" +                            "--Lock released by Thread " +                            Thread.CurrentThread.GetHashCode());        }        //This is a non synchronized method        public void doSomeWorkNoSync()        {          Console.WriteLine("doSomeWorkNoSync()" +                            "--Entered Thread is " +                            Thread.CurrentThread.GetHashCode());          Thread.Sleep(5 * 1000);          Console.WriteLine("doSomeWorkNoSync()" +                            "--Leaving Thread is " +                            Thread.CurrentThread.GetHashCode());        }        [STAThread]        static void Main(string[] args)        {          MI m = new MI();          //Delegate for Non-Synchronous operation          ThreadStart tsNoSyncDelegate =              new ThreadStart(m.doSomeWorkNoSync);          //Delegate for Synchronous operation          ThreadStart tsSyncDelegate =              new ThreadStart(m.doSomeWorkSync);          Thread t1 = new Thread(tsNoSyncDelegate);          Thread t2 = new Thread(tsNoSyncDelegate);          t1.Start();          t2.Start();          Thread t3 = new Thread(tsSyncDelegate);          Thread t4 = new Thread(tsSyncDelegate);          t3.Start();          t4.Start();        }      }    } 

The output from the above listing will be similar to the following (output might vary from computer to computer as Thread IDs might differ):

    doSomeWorkNoSync()--Entered Thread is 2    doSomeWorkNoSync()--Entered Thread is 3    doSomeWorkSync()--Lock held by Thread 4    doSomeWorkNoSync()--Leaving Thread is 2    doSomeWorkNoSync()--Leaving Thread is 3    doSomeWorkSync()--Lock released by Thread 4    doSomeWorkSync()--Lock held by Thread 5    doSomeWorkSync()--Lock released by Thread 5 

In the above listing, the MI class has two methods: doSomeWorkSync() and doSomeWorkNoSync(). The MethodImpl attribute has been applied to the doSomeWorkSync() method to synchronize it, whereas doSomeWorkNoSync() is kept as it is so that multiple threads can access the method at the same time. In the Main() method, threads t1 and t2 access the non-synchronized method and threads t3 and t4 access the synchronized method. In both the methods, the Thread.Sleep() method is added to give sufficient time for another competing thread to enter the method while the first thread is still in the method. The expected behavior of the program should be such that threads t1 and t2 can simultaneously enter the doSomeWorkNoSync() method, whereas only one of the threads (either t3 or t4) will be allowed to enter the doSomeWorkSync() method. If t1 and t2 have the same priority, which thread will get the preference is totally at random; the .NET Framework does not guarantee the order in which the threads will be executed.

If you look at the output carefully, you will find that thread 2 (t1) and thread 3 (t2) entered the method doSomeWorkNoSync() at the same time, whereas, once thread 4 (t3) acquired the lock on the method doSomeWorkSync(), thread 5 (t4) was not allowed to enter the method until thread 4 (t3) released the lock on that method.



 < Day Day Up > 



C# Threading Handbook
C# Threading Handbook
ISBN: 1861008295
EAN: 2147483647
Year: 2003
Pages: 74

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