dcsimg
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

Master Managed Threading and Synchronization Techniques : Page 4

Dive deep into the various synchronization techniques available in the .NET framework, including inter-thread and inter-process synchronization.


advertisement
Synchronization with Mutexes
A mutex is similar to a lock, but:

  • You can use mutexes to synchronize threads across processes.
  • A mutex has thread affinity, meaning that the thread owning the mutex must release it.
  • A mutex is an instantiable type.
  • There are two types of mutexes: local mutexes and Named System mutexes.
Consider the following code:

   class ThreadSafeType
   {
      int counter = 0;
      Mutex mutex = new Mutex();
      public void PrintThreadId()
      {
         mutex.WaitOne();
         for (int i = 0; i < 5; i++)
         {
            counter++;
            Console.WriteLine("Process/Thread id : " + 
               Process.GetCurrentProcess().Id+" / 
               "+Thread.CurrentThread.GetHashCode() + 
               " added one to counter. Counter Value : " + counter);
            Thread.Sleep(1000);
         }
         mutex.ReleaseMutex();
         Console.WriteLine(counter);
      }
   }
When you run the preceding code, the output looks like this:

   Process/Thread id : 1484 / 3 added one to counter. Counter Value : 1
   Process/Thread id : 1484 / 3 added one to counter. Counter Value : 2
   Process/Thread id : 1484 / 3 added one to counter. Counter Value : 3
   Process/Thread id : 1484 / 3 added one to counter. Counter Value : 4
   Process/Thread id : 1484 / 3 added one to counter. Counter Value : 5
   5
   Process/Thread id : 1484 / 4 added one to counter. Counter Value : 6
   Process/Thread id : 1484 / 4 added one to counter. Counter Value : 7
   Process/Thread id : 1484 / 4 added one to counter. Counter Value : 8
   Process/Thread id : 1484 / 4 added one to counter. Counter Value : 9
   Process/Thread id : 1484 / 4 added one to counter. Counter Value : 10
   10
Another common developer need is synchronizing access to files. The code below tries to write to a file without any synchronization mechanism implemented:

   // no synchronization example
   class ThreadSafeType
   {
      public void PrintThreadId()
      {
         using (StreamWriter sw = new StreamWriter("TestFile.txt," true))
         {
            for (int i = 0; i < 5; i++)
            {
               sw.WriteLine("Process/Thread id : " + 
                  Process.GetCurrentProcess().Id + " / " + 
                  Thread.CurrentThread.GetHashCode());
            }
            Thread.Sleep(1000);
         }
      }
   }
A single process running multiple threads will throw the following IOException:

   System.IO.IOException: The process cannot access the file 
      'D:\TestFile.txt' because it is being used by another process.
You can solve the issue by using a mutex as follows (the mutex used here is a local mutex):

   // Using a local mutex for File Access
   class ThreadSafeType
   {
      Mutex mutex = new Mutex();
      public void PrintThreadId()
      {
         mutex.WaitOne();
         using (StreamWriter sw = new StreamWriter(
            "TestFile.txt," true))
         {
            for (int i = 0; i < 5; i++)
            {
               sw.WriteLine("Process/Thread id : " + 
                  Process.GetCurrentProcess().Id + " / " + 
                  Thread.CurrentThread.GetHashCode());
            }
            Thread.Sleep(4000);
         }
         mutex.ReleaseMutex();
      }
   }
Here's the output in the file after implementing the local mutex and running the preceding code:

   Process/Thread id : 2560 / 3
   Process/Thread id : 2560 / 3
   Process/Thread id : 2560 / 3
   Process/Thread id : 2560 / 3
   Process/Thread id : 2560 / 3
   Process/Thread id : 2560 / 4
   Process/Thread id : 2560 / 4
   Process/Thread id : 2560 / 4
   Process/Thread id : 2560 / 4
   Process/Thread id : 2560 / 4
Unfortunately, when you run two instances of this process at the same time, you still get the IOException shown previously. Instead, for inter-process synchronization, you must use named system mutexes as shown in the code below:

   // Named System Mutex example
   class ThreadSafeType
   {
      Mutex mutex = new Mutex(false, "TestFile");
      public void PrintThreadId()
      {
         mutex.WaitOne();
         using (StreamWriter sw = new StreamWriter(
            "TestFile.txt," true))
         {
            for (int i = 0; i < 5; i++)
            {
               sw.WriteLine("Process/Thread id : " + 
                  Process.GetCurrentProcess().Id + " / " + 
                  Thread.CurrentThread.GetHashCode());
            }
            Thread.Sleep(3000);
         }
         mutex.ReleaseMutex();
      }
   }
After running the named system mutex code, here's the output you'll find in the file:

   Process/Thread id : 3480 / 3
   Process/Thread id : 3480 / 3
   Process/Thread id : 3480 / 3
   Process/Thread id : 3480 / 3
   Process/Thread id : 3480 / 3
   Process/Thread id : 4552 / 3
   Process/Thread id : 4552 / 3
   Process/Thread id : 4552 / 3
   Process/Thread id : 4552 / 3
   Process/Thread id : 4552 / 3
   Process/Thread id : 3480 / 4
   Process/Thread id : 3480 / 4
   Process/Thread id : 3480 / 4
   Process/Thread id : 3480 / 4
   Process/Thread id : 3480 / 4
   Process/Thread id : 4552 / 4
   Process/Thread id : 4552 / 4
   Process/Thread id : 4552 / 4
   Process/Thread id : 4552 / 4
   Process/Thread id : 4552 / 4
Note that both the processes and their threads participate.



Thanks for your registration, follow us on our social networks to keep up-to-date