13/32 · 5 min
Three tools that look alike
They all prevent two threads from doing something at once, and they are not interchangeable.
Mutex
One holder at a time, and the holder must be the one who releases it.
lock = threading.Lock()
with lock:
counter += 1 # only one thread here at a timeThe ownership rule is the important part: a mutex is a lock on a thing, held by whoever is using it.
Semaphore
A counter with two operations: wait, which decrements and blocks at zero, and signal, which increments. It has no owner, so one thread may signal a semaphore another thread waited on.
That makes it a different tool despite the surface similarity. A semaphore initialised to 1 behaves like a mutex; initialised to N it limits concurrency to N:
pool = threading.Semaphore(5) # at most 5 concurrent downloads
with pool:
download(url)And with no ownership it can signal between threads, which is how a producer tells a consumer that an item is ready. A mutex cannot express that.
| Mutex | Semaphore | |
|---|---|---|
| Ownership | yes | no |
| Values | locked or not | any count |
| Use | protect shared data | limit concurrency, signal |
Monitor
A higher level construct: data plus the lock that protects it, with the locking implicit. Java's synchronized is one.
public synchronized void deposit(int amount) {
balance += amount; // the lock is taken and released for you
}Monitors add condition variables for the pattern "wait until something is true":
while (queue.isEmpty()) {
wait(); // release the lock and sleep
}The while is not a stylistic choice. A woken thread must re-check, because another thread may have taken the item between the wakeup and reacquiring the lock. Writing if there is a real and well known bug.
Choosing
| Need | Use |
|---|---|
| Protect a variable | mutex |
| At most N at once | semaphore |
| Wait for a condition | condition variable |
| Just a counter | atomic operation, no lock |
And the ordering rule that prevents deadlock applies to all of them: if two locks are ever held together, every thread must take them in the same order.