A bathroom with a single lock. A parking lot with 50 spaces. A restaurant with 10 tables.
These real-world scenarios map directly to two fundamental synchronization primitives: mutex and semaphore.
A mutex is like the bathroom lock. Only one person can use it at a time. A semaphore is like the parking lot. Multiple cars can enter, but only up to the capacity.
In this article, we'll explore:
If you're enjoying this newsletter and want to get even more value, consider becoming a [paid subscriber](https://blog.algomaster.io/subscribe).
As a paid subscriber, you'll unlock all premium articles and gain full access to all [premium courses](https://algomaster.io/newsletter/paid/resources) on [algomaster.io](https://algomaster.io).
A Mutex (Mutual Exclusion) is a synchronization primitive that allows only one thread to access a resource at a time.
Think of it as a key to a room. Only the thread holding the key can enter. Other threads must wait until the key is returned.
The flow of mutex acquisition:
A Semaphore is a synchronization primitive that controls access to a resource by maintaining a count of available permits.
Think of it as a parking lot attendant. The lot has N spaces. Each car that enters takes a permit (decrementing the count). When a car leaves, it returns a permit (incrementing the count). When count reaches zero, new cars must wait.
A semaphore has two fundamental operations:
A semaphore with only two states: 0 or 1. It behaves similarly to a mutex.
A semaphore that allows multiple threads to access a resource, up to a specified limit.
Example: Limiting concurrent database connections
While binary semaphores and mutexes seem similar, they have important differences:
This is the most important distinction:
This makes semaphores useful for signaling between threads, while mutexes are strictly for mutual exclusion.
Because semaphores have no ownership, they can coordinate between different threads. One thread signals an event, another waits for it.
Both mutex and semaphore can be configured for fairness, meaning threads acquire them in the order they requested.
A reentrant (or recursive) mutex allows the same thread to acquire it multiple times without deadlocking.
The mutex tracks how many times it was locked by the owning thread. It only truly releases when the lock count reaches zero.
Semaphores are not reentrant. Each acquire decrements the count regardless of which thread called it.
Mutex and Semaphore are fundamental synchronization primitives:
Key Differences:
When to Use:
Best Practices:
Thank you for reading!
If you found it valuable, hit a like and consider subscribing for more such content every week.
If you have any questions or suggestions, leave a comment.
This post is public so feel free to share it.
P.S. If you're enjoying this newsletter and want to get even more value, consider becoming a [paid subscriber](https://blog.algomaster.io/subscribe).
As a paid subscriber, you'll unlock all premium articles and gain full access to all [premium courses](https://algomaster.io/newsletter/paid/resources) on [algomaster.io](https://algomaster.io).
There are [group discounts](https://blog.algomaster.io/subscribe?group=true), [gift options](https://blog.algomaster.io/subscribe?gift=true), and [referral bonuses](https://blog.algomaster.io/leaderboard) available.
Checkout my [Youtube channel](https://www.youtube.com/@ashishps_1/videos) for more in-depth content.
Follow me on [LinkedIn](https://www.linkedin.com/in/ashishps1/) and [X](https://twitter.com/ashishps_1) to stay updated.
Checkout my [GitHub repositories](https://github.com/ashishps1) for free interview preparation resources.
I hope you have a lovely day!
See you soon, Ashish
[IMAGE 1: Mutex Concept] <!-- Single key/lock protecting a resource -->
[IMAGE 2: Semaphore Concept] <!-- Parking lot with N spaces analogy -->
[IMAGE 3: Binary vs Counting Semaphore] <!-- Visual comparison of permit counts -->
[IMAGE 4: Mutex vs Semaphore Comparison] <!-- Side-by-side feature comparison -->
[IMAGE 5: Producer-Consumer with Semaphores] <!-- Signaling flow between producer and consumer -->
[IMAGE 6: Decision Flowchart] <!-- When to use mutex vs semaphore -->