What is a Mutex
A mutex (short for mutual exclusion) is a synchronization primitive that ensures only one thread can access a shared resource at a time. If thread A holds the mutex, thread B must wait until thread A releases it. This prevents race conditions where two threads corrupt shared data by modifying it simultaneously.
How it works
A mutex has two operations:
- Lock (acquire) — if the mutex is free, the thread takes ownership and proceeds. If another thread already holds it, the calling thread blocks (sleeps) until the mutex is released.
- Unlock (release) — the thread gives up ownership, and one waiting thread (if any) is woken up to acquire it.
The critical section — the code between lock and unlock — runs exclusively. Only one thread executes it at a time.
mutex.lock()
shared_counter += 1 // safe: no other thread can be here
mutex.unlock()
Without the mutex, two threads could read the same value of shared_counter, both increment it, and both write back the same result — losing an update.
Contention is the performance cost. When many threads compete for the same mutex, most are blocked and waiting. High contention turns parallel code into serial code. Strategies to reduce contention include:
- Using finer-grained locks (one per data structure, not one global lock).
- Using lock-free data structures where possible.
- Reducing the time spent holding the lock.
Mutexes are implemented using atomic CPU instructions (like compare-and-swap) combined with OS support for putting threads to sleep when the lock is unavailable.
Why it matters
Mutexes are the most fundamental tool for safe concurrent programming. Every shared mutable data structure in a multithreaded program needs some form of synchronization, and the mutex is the simplest. But mutexes introduce their own problems — deadlocks when two threads lock in opposite order, and performance bottlenecks under contention.
See How Threads Work for synchronization patterns beyond mutexes.