Mutex vs Semaphore

RoadmapsCore CS

Scenario

A mutex is a bathroom key: only one person gets it, and they must return it. A semaphore is a parking lot with 5 spaces: the attendant lets 5 cars in, and anyone can leave to free up a spot.

Mental model

A mutex is about exclusive ownership (locking), while a semaphore is about counting available resources (signaling).

Mutexes protect a single resource by ensuring only one thread accesses it at a time. Semaphores track a pool of identical resources, allowing multiple threads up to a strict limit.

Explanation

When dealing with concurrency, we need practical tools to prevent race conditions. The two most fundamental synchronization primitives provided by operating systems are the mutex and the semaphore. While they are often confused, they serve completely distinct architectural purposes: a mutex is used for locking, and a semaphore is used for signaling and counting.

A Mutex (short for Mutual Exclusion) is a binary lock. When a thread wants to enter a critical section, it acquires the mutex. If another thread already holds it, the new thread is blocked and goes to sleep until the mutex is released. The most critical defining feature of a mutex is ownership: the thread that locks a mutex is the exact same thread that must unlock it. You cannot have Thread A lock a mutex and Thread B unlock it. This strict ownership makes mutexes the perfect tool for protecting shared data like linked lists or banking balances from concurrent modifications.

A Semaphore, invented by Edsger Dijkstra, is essentially an integer counter with two atomic operations: 'wait' (decrements) and 'signal' (increments). If the counter is greater than zero, a thread can decrement it and proceed. If the counter is zero, the thread blocks. Unlike a mutex, a semaphore has absolutely no concept of ownership. Any thread can signal (increment) a semaphore. This makes semaphores incredibly powerful for signaling between threads (e.g., Thread A finishes a task and signals Thread B to wake up) and managing pools of resources, like a connection pool that allows exactly 10 concurrent database connections.

A common point of confusion is the 'Binary Semaphore'—a semaphore initialized to 1. Functionally, a binary semaphore acts like a mutex because it restricts access to one thread at a time. However, even a binary semaphore lacks the ownership requirement of a true mutex. Because operating systems know who owns a mutex, they can provide advanced protections like Priority Inheritance (temporarily boosting the priority of a thread holding a lock to prevent priority inversion), which cannot be done with semaphores.

In system design, use a mutex when you need to protect shared state from corruption. Use a semaphore when you need to track how many items are available or when you need one thread to notify another thread that an event has occurred.

Key points

Common mistakes

Glossary

synchronization primitives
The fundamental, built-in tools provided by an operating system to help programmers safely manage programs that run multiple tasks at the exact same time.
mutex
A digital lock used to guarantee that only one single thread can access a specific piece of shared data at a time, preventing messy collisions.
semaphore
A digital signaling mechanism, like a bouncer with a clicker, used to limit how many threads can access a shared resource (like a pool of database connections) simultaneously.

Recall questions

Questions & answers

Which synchronization primitive is best suited for managing a pool of 10 identical database connections?

A counting semaphore.

Approach: Initialize the semaphore to 10. Threads 'wait' to take a connection and 'signal' when returning it, naturally limiting concurrency to 10.

Can Thread B unlock a mutex that was locked by Thread A?

No.

Approach: Mutexes have strict thread ownership. Attempting to unlock another thread's mutex leads to undefined behavior or OS-level errors.

Continue learning

Previous: Race Condition & Critical Section

Next: Producer-Consumer Problem

Next: Reader-Writer & Dining Philosophers

Return to Core CS Roadmap