Thread synchronization using monitors in C# -Learn how to synchronize threads in executing a piece of common code using locks and monitors with example programs.
Lock is the keyword in C# that will ensure only one thread is executing a piece of code .
The lock keyword ensures that one thread does not enter a critical section of code while another thread is in that critical section.
Please click the following link for synchronization using Lock example.
Lock = Monitor + try finally.
Monitor:
Monitor is also a locking mechanism that will ensure one thread is executing a piece of code at one time.
Monitor is no different from lock but the monitor class provides more control over the synchronization of various threads trying to access the same lock of code.
The Monitor class has the following methods for the synchronize access to a region of code by taking and releasing a lock:
- Monitor.Enter
- Monitor.TryEnter
- Monitor.Exit
Here is the example program how monitors works for synchronization in multi threading.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static object monitor = new object();
static void Main(string[] args)
{
//Both thread will print a same string on console.
Thread t1 = new Thread(printer);
Thread t2 = new Thread(printer);
t1.Start();
t2.Start();
t2.Join();
}
static void printer()
{
String arr = "Printer is printing!!!";
try
{
//hold lock as console is shared between threads.
Monitor.Enter(monitor);
for (int i = 0; i < arr.Length; i++)
{
Console.Write(arr[i]);
}
}
finally
{
//Release lock
Monitor.Exit(monitor);
}
}
}
Output
Printer is printing!!!Printer is printing!!!
Monitor locks objects .While you can pass a value type to Enter and Exit, it is boxed separately for each call.
Monitor has signalling mechanism, like wait , pulse and pulseall methods for signalling / communication between threads.
Monitor pulse, wait and pulseAll Method
Monitor.wait(): A thread waits for other threads to notify.
Monitor.pulse(): A thread notifies to another thread.
Monitor.pulseAll(): A thread notifies all other threads within a process.
Below is the example to print the number sequence in even and odd using wait an pulse methods.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static object monitor = new object();
static void Main(string[] args)
{
Thread oddThread = new Thread(Odd);
Thread evenThread = new Thread(Even);
//Start even thread.
evenThread.Start();
//puase for 10 ms, to make sure even thread has started
//or else odd thread may start first resulting other sequence.
Thread.Sleep(100);
//Start odd thread.
oddThread.Start();
oddThread.Join();
}
//printing of Odd numbers
static void Odd()
{
try
{
//hold lock as console is shared between threads.
Monitor.Enter(monitor);
for (int i = 1; i <= 10; i = i + 2)
{
//Complete the task ( printing odd number on console)
Console.Write(" " + i);
//Notify other thread that is to eventhread
//that I'm done you do your job
Monitor.Pulse(monitor);
//I will wait here till even thread notify me
Monitor.Wait(monitor);
}
}
finally
{
//Release lock
Monitor.Exit(monitor);
}
}
//printing of even numbers
static void Even()
{
try
{
//hold lock
Monitor.Enter(monitor);
for (int i = 0; i <= 10; i = i + 2)
{
//Complete the task ( printing even number on console)
Console.Write(" " + i);
//Notify other thread- here odd thread
//that I'm done you do your job
Monitor.Pulse(monitor);
//I will wait here till odd thread notify me
Monitor.Wait(monitor);
}
}
finally
{
Monitor.Enter(monitor);
}
}
}
Output
0 1 2 3 4 5 6 7 8 9 10
Monitor.Pulse() method is notifying to other thread to use the resource after its completion.. Monitor.wait() method-waits for other thread to notify for resource usage.