Thread Synchronization

Introduction

Thread Synchronization is a mechanism which ensures that two or more concurrent process or threads do not execute some particular section of program especially critical section. In this technique one thread executes the critical section of a program and other thread wait until the first thread finishes execution.
 
If proper synchronization mechanism will be not applied then race condition will happen.
 
Thread Synchronization Deals with the following conditions:
  1. Deadlock
  2. Starvation
  3. Priority Inversion
  4. Busy Waiting
The Following are some classic problems of Synchronization:
  1. The Producer-Consumer Problem
  2. The Readers-Writers Problem
  3. The Dining Philosopher Problem
These problems are used to test every newly proposed synchronization techniques.

Synchronization is handled with the following four categories:  

The following are the four categories to handle Synchronization mechanism:
  1. Blocking Methods
  2. Locking Construct
  3. Signaling
  4. No Blocking Synchronization
Blocking Methods 

In this technique, one thread wait for the another thread to finish for a particular period of time. Here, the execution is paused for some reason. The following are some Blocking methods in C#:
  1. Sleep
  2. Join
  3. Task.Wait
Sleep
 
It pauses the execution of a program for a defined time. It does not utilize CPU during the pause time. It is useful for waiting on an external Task.
  1. Thread.Sleep(300)  
Join
 
It is  also a part of blocking mechanism in the thread synchronization. It is similar to Sleep but it does not pauses all threads. It pauses the calling thread until the thread whose join method is called has completed. 
 
Example: 
  1. class Program    
  2. {    
  3.     static void Main(string[] args)    
  4.     {    
  5.         Thread thread1 = new Thread(Method1);    
  6.         thread1.Start();    
  7.   
  8.         Thread thread2 = new Thread(Method2);    
  9.         thread2.Start();    
  10.   
  11.         thread1.Join();    
  12.         Console.WriteLine("After Thread1");    
  13.   
  14.         thread2.Join();    
  15.         Console.WriteLine("After Thread2");    
  16.         Console.ReadKey();    
  17.   
  18.     }    
  19.   
  20.     private static void Method2(object obj)    
  21.     {    
  22.         Console.WriteLine("Thread1 Executed.");    
  23.     }    
  24.   
  25.     private static void Method1(object obj)    
  26.     {    
  27.         Console.WriteLine("Thread2 Executed");    
  28.     }    
  29.   
  30.        
  31. }  
Output:
 
Thread2 Executed.
Thread1 Executed.
After Thread1
After Thread2 
 
Task.Wait 
 
It is a blocking Synchronization method which allows the calling thread to wait until the current task has been completed.  
 
Example:
  1. class Program    
  2. {    
  3.     static void Main(string[] args)    
  4.     {    
  5.         Task task = Task.Run(() =>    
  6.         {    
  7.             Random randomNumbers = new Random();    
  8.             long sum = 0;    
  9.             int count = 1000000;    
  10.             for (int i = 1; i <= count; i++)    
  11.             {    
  12.                 int randomNumber = randomNumbers.Next(0, 101);    
  13.                 sum += randomNumber;    
  14.             }    
  15.   
  16.             Console.WriteLine("Total:{0}", sum);    
  17.             Console.WriteLine("Count: {0}", count);    
  18.         });    
  19.         task.Wait();    
  20.             
  21.         Console.ReadKey();    
  22.     }    
  23. }  
Output:

Total: 50028434
Count: 1000000 

Locking 

Locking is also a synchronization mechanism. It limits the access to a resource in multiple thread. Exclusive locking mechanism is used for it.
 
The following are the two main Locking mechanism:
  1. Lock
  2. Mutex
Lock
 
It locks the critical section of code so that only one thread can execute the critical section of code at a time. If another thread tries to enter into critical section of code then it is prevented and blocked and then it will wait until the object is released from the using thread.
 
Example:
  1.  class Program    
  2.  {    
  3.      decimal totalBalance =50000;    
  4.      private Object myLock = new Object();    
  5.   
  6.      static void Main(string[] args)    
  7.      {    
  8.          Program program = new Program();    
  9.          program.WithDraw(5000);          
  10.          Console.ReadKey();    
  11.      }    
  12.   
  13.      public  void WithDraw(decimal amount)    
  14.      {    
  15.          lock (myLock)    
  16.          {    
  17.              if (amount > totalBalance)    
  18.              {    
  19.                  Console.WriteLine("Insufficient Amount.");    
  20.              }    
  21.   
  22.              totalBalance -= amount;    
  23.              Console.WriteLine("Total Balance {0}",totalBalance);    
  24.          }    
  25.      }    
  26.   
  27.  }   
Output:

Total Balance 45000 
 
Note: Avoid lock on a public type, or instances beyond the control of code.
 
Mutex

Mutex stands for Mutual Exclusion. The Mutex type ensures blocks of code are executed only once at a time. It is basically used in a situation where resources has to be shared by multiple threads simultaneously.  

X

Build smarter apps with Machine Learning, Bots, Cognitive Services - Start free.

Start Learning Now