OS Notes
Understanding mutex locks for mutual exclusion — acquire and release operations, spinlocks vs blocking mutexes, recursive mutexes, and practical mutex usage patterns.
Introduction
A mutex (short for MUTual EXclusion) is the simplest and most intuitive synchronization tool. It is a lock that a process acquires before entering a critical section and releases when leaving. Only one process can hold the mutex at a time — any other process trying to acquire it must wait until it is released.
Think of a mutex like a bathroom door lock. When you enter, you lock the door (acquire). Nobody else can enter while you are inside. When you leave, you unlock (release), and the next person waiting can enter. Simple, effective, and universally understood.
Basic Mutex Operations
Spinlock Implementation
The simplest mutex implementation uses busy waiting (spinning):
typedef struct {
int flag; // 0 = unlocked, 1 = locked
} SpinLock;
void acquire(SpinLock *lock) {
while (test_and_set(&lock->flag) == 1)
; // Spin — keep trying until we get it
}
void release(SpinLock *lock) {
lock->flag = 0;
}When to use spinlocks: On multi-core systems when the critical section is very short (tens of instructions). The cost of spinning for a few microseconds is less than the cost of putting the thread to sleep and waking it up later.
When NOT to use spinlocks: On single-core systems (spinning wastes the only CPU) or when the critical section is long (waste of CPU time).
Blocking Mutex (Sleep Lock)
For longer critical sections, a blocking mutex is more efficient:
typedef struct {
int flag;
Queue *wait_queue; // Processes waiting for this lock
} Mutex;
void acquire(Mutex *lock) {
if (test_and_set(&lock->flag) == 1) {
// Lock is taken — go to sleep
add_to_queue(lock->wait_queue, current_process);
block(); // Remove from CPU, save in wait queue
}
}
void release(Mutex *lock) {
if (!is_empty(lock->wait_queue)) {
Process *p = remove_from_queue(lock->wait_queue);
wakeup(p); // Wake one waiting process
} else {
lock->flag = 0; // Simply unlock
}
}POSIX Mutex (pthreads)
Mutex Properties
Ownership
A mutex has the concept of ownership — only the thread that acquired it can release it. This prevents accidental or malicious unlocking by other threads.
Recursive Mutex
A normal mutex deadlocks if the owner tries to acquire it again. A recursive mutex allows the same thread to acquire it multiple times (maintaining a count) without deadlocking:
pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&lock, &attr);
// Same thread can lock multiple times:
pthread_mutex_lock(&lock); // count = 1
pthread_mutex_lock(&lock); // count = 2 (no deadlock!)
// ... critical section ...
pthread_mutex_unlock(&lock); // count = 1
pthread_mutex_unlock(&lock); // count = 0 (actually unlocked)Mutex vs Semaphore
| Feature | Mutex | Semaphore |
|---|---|---|
| Purpose | Mutual exclusion only | Mutual exclusion OR counting |
| Values | 0 or 1 (locked/unlocked) | 0 to N |
| Ownership | Yes (only owner unlocks) | No (any process can signal) |
| Use case | Protecting critical sections | Resource pools, signaling |
Common Mutex Mistakes
- Forgetting to unlock: Thread acquires mutex then crashes or returns early — deadlock
- Double locking: Non-recursive mutex locked twice by same thread — self-deadlock
- Lock ordering violations: Two mutexes locked in different orders — deadlock
- Holding too long: Keeping mutex while doing I/O — poor concurrency
Real-World Analogy
A mutex is like a talking stick in a group discussion. Only the person holding the stick (owning the mutex) can speak (access the critical section). When done, they pass the stick (release). If someone wants to speak and the stick is taken, they raise their hand and wait (block) or keep checking (spin). A recursive mutex is like allowing the speaker to pick up the stick again to make a sub-point without giving it up first.
Key Takeaways
- A mutex provides mutual exclusion — only one thread holds it at a time
- Spinlocks busy-wait and are efficient for very short critical sections on multi-core
- Blocking mutexes sleep and are efficient for longer critical sections
- Ownership ensures only the acquiring thread can release the mutex
- Recursive mutexes allow the same thread to lock multiple times without deadlocking
- Always release mutexes even on error paths (use RAII in C++ or try-finally)
- Lock ordering discipline prevents deadlocks when using multiple mutexes
Exam Focus
Revise definitions, diagrams, examples, and short-answer points for Mutex Locks.
Interview Use
Prepare one clear explanation, one practical example, and one common mistake for this Operating Systems topic.
Search Terms
operating-systems, operating systems, operating, systems, process, synchronization, mutex, mutex locks
Related Operating Systems Topics