Mutex, Semaphore & SemaphoreSlim in C# β Master Thread Synchronization!
Hey there, fellow C# coder! π Ever faced multiple threads fighting for the same resource? Maybe two users trying to access a file at the same time?
Well, that’s where Mutex in Thread, Semaphore in Thread, and SemaphoreSlim in Thread come to the rescue! π These tools help us control access to shared resources and prevent race conditions.
Today, Iβll break down Mutex, Semaphore, and SemaphoreSlim in the simplest way possible. We’ll see how they work, when to use them, and real-world examples. Let’s go! π―
π What You Are Going to Learn in This Lesson?
βοΈ What is Mutex in Thread and how it works?
βοΈ What is Semaphore in Thread and when to use it?
βοΈ What is SemaphoreSlim in Thread and how it improves performance?
βοΈ Real-world examples of controlling shared resources.
βοΈ Multiple coding examples with detailed explanations.
π Why Do We Need Mutex, Semaphore, and SemaphoreSlim?
Imagine this:
You’re in a public restroom. Only one person can enter at a time. π»
You lock the door while you’re inside. (This is like a Mutex!)
Now imagine there are 5 stalls and 10 people waiting. Only 5 can enter at a time. (This is like a Semaphore!)
In C# multithreading, when multiple threads try to access shared resources, we must control how many threads can enter at a time. Thatβs exactly what Mutex, Semaphore, and SemaphoreSlim do! π‘
π What is Mutex in Thread?
Mutex (short for Mutual Exclusion) ensures only one thread can access a resource at a time.
If Thread A is using the resource, Thread B must wait until Thread A is done.
Mutex can be used across multiple processes (not just threads).
Β
β Syntax of Mutex
Mutex mutex = new Mutex();
π Example 1: Using Mutex in Thread
Letβs see how Mutex ensures that only one thread writes to the console at a time.
using System;
using System.Threading;
class Program
{
static Mutex mutex = new Mutex();
static void PrintMessage(string message)
{
mutex.WaitOne(); // Acquire the lock
try
{
Console.WriteLine($"[{Thread.CurrentThread.ManagedThreadId}] {message}");
Thread.Sleep(1000); // Simulating work
}
finally
{
mutex.ReleaseMutex(); // Release the lock
}
}
static void Main()
{
for (int i = 0; i < 3; i++)
{
new Thread(() => PrintMessage("Hello from thread!")).Start();
}
}
}
β Expected Output
[3] Hello from thread!
[4] Hello from thread!
[5] Hello from thread!
Each thread waits for its turn before printing the message.
π What is Semaphore in Thread?
Semaphore allows a fixed number of threads to access a resource simultaneously.
If the limit is 3, only 3 threads can enter at a time.
Other threads must wait until a slot is free.
Β
β Syntax of Semaphore
Semaphore semaphore = new Semaphore(allowedThreads, maxThreads);
π Example 2: Using Semaphore in Thread
Letβs say we have 5 customers but only 2 ATM machines. Semaphore ensures that only 2 customers can access an ATM at the same time.
using System;
using System.Threading;
class Program
{
static Semaphore semaphore = new Semaphore(2, 2); // Max 2 threads
static void UseATM(string name)
{
Console.WriteLine($"{name} is waiting to use ATM...");
semaphore.WaitOne(); // Wait for a free slot
try
{
Console.WriteLine($"{name} is using the ATM.");
Thread.Sleep(2000); // Simulating ATM use
Console.WriteLine($"{name} has finished.");
}
finally
{
semaphore.Release(); // Release the slot
}
}
static void Main()
{
for (int i = 1; i <= 5; i++)
{
new Thread(() => UseATM($"Customer {i}")).Start();
}
}
}
β Expected Output
Customer 1 is waiting to use ATM...
Customer 2 is waiting to use ATM...
Customer 1 is using the ATM.
Customer 2 is using the ATM.
Customer 3 is waiting to use ATM...
Customer 4 is waiting to use ATM...
Customer 5 is waiting to use ATM...
Customer 1 has finished.
Customer 3 is using the ATM.
Customer 2 has finished.
Customer 4 is using the ATM.
...
Only 2 customers use the ATM at a time, and others wait!
β‘ What is SemaphoreSlim in Thread?
SemaphoreSlim
is a lighter, faster version of Semaphore.
It works only within a single process.
Itβs faster than
Semaphore
because it uses less OS resources.
Β
β Syntax of SemaphoreSlim
SemaphoreSlim semaphoreSlim = new SemaphoreSlim(allowedThreads);
π Example 3: Using SemaphoreSlim in Thread
Letβs modify our ATM example using SemaphoreSlim
.
using System;
using System.Threading;
class Program
{
static SemaphoreSlim semaphoreSlim = new SemaphoreSlim(2); // Allow 2 threads
static void UseATM(string name)
{
Console.WriteLine($"{name} is waiting to use ATM...");
semaphoreSlim.Wait(); // Wait for a free slot
try
{
Console.WriteLine($"{name} is using the ATM.");
Thread.Sleep(2000); // Simulating ATM use
Console.WriteLine($"{name} has finished.");
}
finally
{
semaphoreSlim.Release(); // Release the slot
}
}
static void Main()
{
for (int i = 1; i <= 5; i++)
{
new Thread(() => UseATM($"Customer {i}")).Start();
}
}
}
β Output (Same as Semaphore but Faster!)
Same behavior, but SemaphoreSlim
is optimized for better performance.
π€ Mutex vs Semaphore vs SemaphoreSlim
Feature | Mutex | Semaphore | SemaphoreSlim |
---|---|---|---|
Threads Allowed | 1 | Multiple (fixed) | Multiple (fixed) |
Process Scope | Multiple Processes | One Process | One Process |
Performance | Slower | Medium | Faster |
When to Use? | Exclusive access | Shared resources | Performance optimization |
π Use Mutex for exclusive access (e.g., file locking).
βοΈ Use Semaphore when you need to limit access (e.g., ATM machines).
β‘ Use SemaphoreSlim for faster, lightweight thread management.
π― Conclusion β Why This is Important?
β
Mutex in Thread ensures only one thread accesses a resource.
β
Semaphore in Thread allows a fixed number of threads.
β
SemaphoreSlim in Thread improves performance for single-process applications.
Β
π Next What?
π Great job! You now understand Mutex in Thread, Semaphore in Thread, and SemaphoreSlim in Thread!
But wait, thereβs more! π
Next up: AutoResetEvent and ManualResetEvent in C# β Master Thread Signaling! Stay tuned! π₯