What is the difference between lock, mutex, and semaphore in multithreading?
What is the difference between lock, mutex, and semaphore in multithreading?
🔐 1. lock (Monitor)
✅ What is it?
A C# keyword (shorthand for Monitor.Enter / Monitor.Exit).
Used to synchronize access to a critical section of code by one thread at a time.
🧠 Key Points:
Works within the same process (not across processes).
Automatically releases the lock even if an exception occurs (thanks to syntactic sugar).
🧪 Example:
private object _lockObj = new object();
lock (_lockObj)
{
// Only one thread can enter here at a time
sharedResource++;
}
🧭 Analogy:
Imagine a single bathroom key in a house. Only one person (thread) can hold the key and use the bathroom at a time.
🛑 2. Mutex (Mutual Exclusion)
✅ What is it?
A thread synchronization object that can work across multiple processes.
Slower than lock due to kernel-level handling.
🧠 Key Points:
Useful when different applications need to coordinate access to a resource (e.g., file).
Must be manually released using mutex.ReleaseMutex().
🧪 Example:
Mutex mutex = new Mutex(false, “MyAppMutex”);
if (mutex.WaitOne())
{
try
{
// Critical section
}
finally
{
mutex.ReleaseMutex();
}
}
🧭 Analogy:
A public restroom key that you check out from the reception. Even people from outside your home (other processes) can queue up and use it.
🚦 3. Semaphore
✅ What is it?
A synchronization primitive that limits the number of threads that can access a resource simultaneously.
Useful for managing a pool of limited resources.
🧠 Key Points:
Semaphore can be used within the same process.
SemaphoreSlim is a lightweight version used in .NET for intra-process scenarios.
Semaphore can have more than one slot—unlike Mutex or lock.
🧪 Example:
SemaphoreSlim semaphore = new SemaphoreSlim(3); // Allow 3 threads
await semaphore.WaitAsync();
try
{
// Code where up to 3 threads can execute in parallel
}
finally
{
semaphore.Release();
}
🧭 Analogy:
Imagine a parking lot with 3 spaces. Only 3 cars (threads) can park at the same time. Others must wait until a spot is freed.
| Feature | lock / Monitor | Mutex | Semaphore |
|---|---|---|---|
| Access | Single thread | Single thread | Multiple threads (limited) |
| Process Scope | Same process only | Cross-process capable | Same or cross process |
| Performance | Fast (user-mode) | Slower (kernel-mode) | Fast (user-mode via SemaphoreSlim) |
| Auto-release | Yes (with lock) |
No (manual) | No (manual) |
| Use Case | Protect small code blocks | Synchronize across apps | Limit simultaneous access to resources |
| .NET Support | C# keyword (lock) |
System.Threading.Mutex |
Semaphore / SemaphoreSlim |
💡 When to Use What?
Scenario Use
You want to synchronize access to a method/section within the same app ✅ lock
You want to synchronize across multiple apps/processes ✅ Mutex
You want to limit concurrent access (like a thread pool or connection pool) ✅ Semaphore
🔥 Pro Tip to Impress the Interviewer:
“While lock is the easiest and fastest way to synchronize access in a single process, Mutex allows cross-process communication at the cost of performance. On the other hand, Semaphore is powerful when managing a bounded number of threads, like when building a thread-safe resource pool or controlling access to a limited service like DB connections.”