Skip to content

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.

python
lock = threading.Lock()

with lock:
    counter += 1        # only one thread here at a time

The 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:

python
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.

MutexSemaphore
Ownershipyesno
Valueslocked or notany count
Useprotect shared datalimit concurrency, signal

Monitor

A higher level construct: data plus the lock that protects it, with the locking implicit. Java's synchronized is one.

java
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":

java
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

NeedUse
Protect a variablemutex
At most N at oncesemaphore
Wait for a conditioncondition variable
Just a counteratomic 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.