Mutex
Mutual exclusion: at most one holder. The lock you actually want most of the time.
Level: intermediate
What is it?
A mutex is a lock with ownership: acquire, enter the critical section, release. Only the owner should unlock. Implementations: TAS/CAS spinlocks (short), futexes (spin then sleep), adaptive mutexes.
Why does it matter?
Race conditions are 'you needed a mutex' (or a lock-free protocol you can prove). Deadlocks are 'you needed an order on mutexes'.
Mental model
A bathroom key. One holder. Don't copy the key (unlock from the other thread). Don't wait in the bathroom for a second key (lock order).
How it works
- Protect data, not code. The invariant lives on the data.
- Hold time is the scalability limit. Do not I/O under a lock.
- Lock ordering prevents deadlock. Document the order.
- Try-lock and timed lock exist; they are not a substitute for a design.
Code example: The shape, not the API
lock(&m);
account->balance -= 10; /* invariant: balance consistent */
unlock(&m);Real-world usage
- pthreads
- synchronized
- std::mutex
Common mistakes
- Locking too coarse (one big mutex) or too fine (deadlock soup)
- Forgetting the data is still racy if you read it without the lock 'because I only read'
Interview questions
Mutex vs semaphore?
A mutex has ownership and is binary. A semaphore is a counter: it can permit N and is often used for signaling, not just exclusion.
Why not spin forever?
A busy-wait burns a core. Spin briefly if the critical section is tiny and the holder is on another core; then sleep (futex).