Here we learn c# thread safety with mutex and semaphore, both are type of locking mechanism that helps controlling how many threads can perform task concurrently.
Semaphore: To control number of threads can access a resource concurrently.
Mutex: Prevent two threads from performing one or more actions simultaneously.
Mutex is a class under system.threading namespace
public sealed class Mutex : WaitHandle { }
Mutex class provide mechanism to prevent two threads from performing one or more actions simultaneously. Mutex is like a C# lock, but Mutex can work across multiple processes.
private static Mutex mutex = new Mutex(); static void MutexDemo() { try { bool isSafe= mutex.WaitOne(); if (isSafe) { Console.WriteLine("{0} has entered", Thread.CurrentThread.Name); Thread.Sleep(500); Console.WriteLine("{0} Leaving", Thread.CurrentThread.Name); } } finally { mutex.ReleaseMutex(); } }
Now call the above MutexDemo
method from multiple threads to see the result.
public static void MutexExample() { for (int i = 0; i < 4; i++) { Thread t = new Thread(MutexDemo); t.Name = string.Format("Thread {0} :", i + 1); t.Start(); } }
Here is the output of above code.
Thread 3 : has entered Do Stuff Thread 3 : is leaving Thread 4 : has entered Thread 4 : is leaving Thread 1 : has entered Thread 1 : is leaving Thread 2 : has entered Thread 2 : is leaving All Done
Here are some mutex methods
Wait until it is safe to enter
ReleaseMutex unblock other threads that are trying to gain ownership of the mutex.
We can set the limits the number of threads that can access any resource concurrently, with semaphore we can set the min and max number.
using System.Threading; static Semaphore _pool = new Semaphore(0, 2);
We can specify initial number and maximum number of concurrent access allowed for any resources, like in above example i have 0 and 2 (maximum).
static Semaphore _pool = new Semaphore(0, 4); static int _padding; public static void SemaphoreDemo() { Console.WriteLine($"{Thread.CurrentThread.Name} processing"); try { _pool.WaitOne(); int padding = Interlocked.Add(ref _padding, 100); Console.WriteLine($"{Thread.CurrentThread.Name} is in"); Thread.Sleep(1000 + padding); Console.WriteLine($"{Thread.CurrentThread.Name} completed"); } finally { //Release() method to releage semaphore _pool.Release(); } }
Now call the above SemaphoreDemo
method from multiple threads to see the result.
public static void SemaphoreExample() { for (int i = 0; i < 5; i++) { Thread t = new Thread(new ThreadStart(SemaphoreDemo)); t.Name = string.Format($"(Thread-name:{i})"); t.Start(); } Thread.Sleep(500); _pool.Release(4); }
Here are some important methods of Semaphore
Blocks the current thread until the current WaitHandle receives a signal
Release the block, so that other thread can enter, we also can specify number of time semaphore exit.
Learn more about how to use Mutex in C# program.
You may be interested in following posts