Introduction
Mutexes and semaphores both control access in concurrent programs, but they are not the same synchronization primitive. The cleanest difference is ownership versus permits.
A mutex is mainly used to protect shared state through mutual exclusion. A semaphore is mainly used to count available permissions or signal that an event has happened.
Revisiting Mutex and Semaphore
A mutex is a mutual-exclusion lock that allows only one thread to enter a protected critical section at a time.
Basic flow: Thread locks mutex => Enters critical section => Updates shared state => Unlocks mutex
If T1 holds the mutex, T2 must wait until T1 unlocks it. The thread that locks the mutex is expected to unlock it, making mutexes suitable for protecting shared data such as maps, queues, counters, caches, and object state.
A semaphore is an integer synchronization variable used through wait and signal.
wait: Takes one permit if available; otherwise, the thread blocks.
signal: Returns a permit and may wake a waiting thread.
Counting meaning: The semaphore value represents available permits.
Unlike a mutex, a semaphore does not necessarily have ownership. One thread may call wait, while another can later call signal.
Revisiting Mutex and Semaphore
Core Difference
A mutex answers the question: who owns the protected region right now? A semaphore answers the question: how many permits are available, or has the required event been signaled?
Aspect | Mutex | Semaphore |
|---|---|---|
Main idea | Mutual exclusion with ownership | Permit counting or signaling |
Main use | Protect shared state or critical section | Manage resources, limits, or events |
Ownership | The locking thread owns it | Usually no strict owner |
Release rule | Same owner should unlock | Another thread may signal |
Typical operations |
|
|
Common example | Shared map, queue, counter | Connection pool, producer-consumer signal |
Binary Semaphore vs Mutex
A binary semaphore has only two values: 0 and 1. Because it represents one permit, it can sometimes behave like a lock.
That similarity is useful but also misleading. A mutex has ownership semantics, while a binary semaphore is still a semaphore. With a binary semaphore, one thread can wait and another thread can signal, which is valid for event coordination.
So the values may look similar, but the meaning is different. Same values do not mean same behavior.
When to Use Each
Use a mutex when the problem is shared-state protection.
Critical section: Only one thread should execute the protected code.
Shared data: A map, queue, counter, cache, or object must stay consistent.
Ownership matters: The same thread that enters the region should leave and unlock it.
Use a semaphore when the problem is permits, limits, or ordering.
Limited resources: Only
Nthreads should useNidentical resources.Concurrency limit: A fixed number of workers may proceed at once.
Event signaling: One thread waits until another thread signals.
Producer-consumer coordination: Producers and consumers coordinate available items or spaces.
When to Use Mutex & Semaphore
Common Mistakes
Using a semaphore as a mutex without ownership clarity: This can make reasoning harder.
Using a mutex to count many resources: A mutex does not naturally represent
Npermits.Ignoring binary semaphore semantics: A binary semaphore may look like a mutex but can be signaled by another thread.
The safest approach is to identify the actual problem first: shared-state protection, resource counting, or event ordering.
Summary
A mutex is mainly for mutual exclusion. It protects a critical section or shared state through ownership, where the thread that locks the mutex should unlock it.
A semaphore is mainly for permits and signaling. It can count identical resources, limit concurrency, coordinate producer-consumer work, or make one thread wait until another thread signals an event.
Be the first to add a comment.