Monitor, Mutex, and lock are fundamental synchronization mechanisms in C#. Let’s go step by step so you can explain them clearly in your blog or interview.
🔹 1. The Problem They Solve
When multiple threads run in parallel, they may try to access or modify the same shared resource (like a file, database record, or variable).
This can lead to race conditions (unexpected results due to simultaneous access).
Solution → Synchronization mechanisms ensure only one thread at a time can access critical sections of code.
🔹 2. lock Keyword
- Definition: A simplified way to use
Monitorin C#. It ensures that only one thread enters a block of code at a time. - How it works: Internally,
lockusesMonitor.EnterandMonitor.Exit. - Usage:
static object _lock = new object();
static int counter = 0;
lock (_lock)
{
counter++;
Console.WriteLine($"Counter: {counter}");
}
- Step-by-step:
- Thread requests access to the block.
- If another thread is inside, it waits.
- Once the block is free, the thread enters.
- When finished, the lock is released.
Best for: Simple critical sections inside the same process.
🔹 3. Monitor
- Definition: Provides more control than
lock. It allows threads to wait and signal each other. - Key Methods:
Monitor.Enter(obj)→ Acquire lock.Monitor.Exit(obj)→ Release lock.Monitor.Wait(obj)→ Release lock temporarily and wait.Monitor.Pulse(obj)→ Signal one waiting thread.Monitor.PulseAll(obj)→ Signal all waiting threads.
- Usage:
static object _lock = new object();
static int counter = 0;
Monitor.Enter(_lock);
try
{
counter++;
Console.WriteLine($"Counter: {counter}");
}
finally
{
Monitor.Exit(_lock); // Always release in finally
}
- Step-by-step:
- Thread enters using
Monitor.Enter. - Executes critical section.
- Can use
WaitandPulsefor coordination. - Releases lock with
Monitor.Exit.
- Thread enters using
Best for: Complex scenarios where threads need to communicate (producer-consumer patterns).
🔹 4. Mutex
- Definition: A synchronization primitive that works across processes (not just threads in the same process).
- Usage:
using System.Threading;
class Program
{
static Mutex mutex = new Mutex();
static void Main()
{
if (mutex.WaitOne())
{
try
{
Console.WriteLine("Mutex acquired.");
Thread.Sleep(2000); // simulate work
}
finally
{
mutex.ReleaseMutex();
Console.WriteLine("Mutex released.");
}
}
}
}
- Step-by-step:
- Thread/process requests the mutex using
WaitOne(). - If available, it enters; otherwise, it waits.
- Executes critical section.
- Releases mutex with
ReleaseMutex().
- Thread/process requests the mutex using
Best for: Synchronizing resources across multiple processes (e.g., two different applications accessing the same file).
🔹 5. Summary Comparison
| Feature | lock | Monitor | Mutex |
|---|---|---|---|
| Scope | Threads in same process | Threads in same process | Threads across processes |
| Ease of Use | Very simple | More complex | Moderate |
| Extra Features | None | Wait/Pulse signaling | Cross-process synchronization |
| Performance | Fastest | Slightly slower | Slowest (OS-level object) |
| Best Use Case | Simple critical sections | Complex thread coordination | Multi-process resource sharing |
🎯 Conclusion
- Use lock for simple thread safety.
- Use Monitor when you need advanced coordination between threads.
- Use Mutex when synchronization must extend across multiple processes.
By explaining these step-by-step, you’ll show both conceptual clarity and practical expertise—perfect for interviews and blog readers.