Mutex vs semaphore
“What is the difference between a mutex and a semaphore? Is a binary semaphore the same thing as a mutex? When would you use each?”
What this tests
- Ownership as the defining property of a mutex
- A semaphore as a counter for signalling and resource pools
- Why a binary semaphore is not a mutex
- Implementation: futex fast path, spinning vs sleeping, and contention symptoms
Answers by level
Read the beginner answer first and notice what is missing.
A mutex protects a critical section and has an owner: the thread that locked it is the only one allowed to unlock it. That rule enables things a counter cannot: recursive locking, error checking (unlock by a non-owner is a bug the library can report), and priority inheritance — the kernel knows who holds it and can boost that thread when a higher-priority thread waits (Mutexes).
A semaphore is a counter with two operations: wait (decrement, block if zero) and signal (increment, wake a waiter). It has no owner — any thread, or an interrupt handler, may signal. That makes it a signalling primitive: a producer signals "one item is available", a consumer waits; N permits bound how many threads may use a pool of N connections at once (Semaphores and Condition Variables).
So a binary semaphore is *not* a mutex. It can be released by a thread that never acquired it — which is a feature when thread A hands a resource to thread B, or an ISR wakes a task — and a liability when used as a lock, because nothing stops the wrong thread from "unlocking", and there is no priority inheritance. For plain mutual exclusion use a mutex; for "wait until someone tells me" use a semaphore or, in most user-space code, a condition variable paired with a mutex; for "at most N concurrently" use a counting semaphore.
Both cost the same when uncontended and differ under contention only in what they express. The failure modes differ too: mutexes deadlock through ordering; semaphores leak permits (a path that returns without signalling) so the pool slowly shrinks until everyone waits forever.
Green flags · Red flags
- Names ownership as the difference
- Explains what ownership enables (priority inheritance, error checking)
- Describes the semaphore as signalling and pooling, releasable by non-acquirers
- Mentions condition variables as the usual signalling tool with a mutex
- Knows the futex fast path and what contention costs
- "Binary semaphore = mutex"
- Cannot say when a non-owner releasing is desirable
- Thinks uncontended locking is expensive