What is the difference between a semaphore and a mutex?
sobes.tech AI
Answer from AI
Semaphore is a generalized synchronization mechanism used to control access to a limited resource by multiple competing threads. It maintains an integer value that decreases when a resource is acquired and increases when released. If the semaphore value is zero, a capture attempt blocks the thread until another thread releases the resource. It can be used to limit the number of threads running simultaneously.
Mutex (mutual exclusion) is a binary semaphore that can be in either a locked or unlocked state. It is used to protect critical sections of code from concurrent access by multiple threads. Only one thread can acquire the mutex at any given time. The thread that has acquired the mutex cannot be interrupted by another thread trying to acquire the same mutex. If an attempt is made to acquire a locked mutex, the thread will be blocked until it is released.
Key differences:
| Characteristic | Semaphore | Mutex |
|---|---|---|
| Type | Generalized synchronization mechanism | Binary semaphore (a specific case of semaphore) |
| Value | Integer (>= 0) | Binary (0 or 1) |
| Purpose | Managing access to resources, limiting threads | Protecting critical sections, mutual exclusion |
| Owner | May not have an owner | Always has an owner (the thread that acquired it) |
| Usage in iOS | DispatchSemaphore |
Often implemented via DispatchQueue.sync or NSRecursiveLock in some scenarios |
Example of using a mutex to protect a critical section:
// In the context of GCD (Grand Central Dispatch)
let serialQueue = DispatchQueue(label: "com.example.criticalSection")
serialQueue.sync {
// Critical section of code
// Only one thread can be here at any given time
}
Example of using a semaphore to limit parallel tasks:
// In the context of GCD (Grand Central Dispatch)
let semaphore = DispatchSemaphore(value: 3) // Allow 3 parallel tasks
DispatchQueue.global().async {
semaphore.wait() // Decrease semaphore value by 1. Blocks if value = 0.
// Code of the task executed in parallel
print("Task is running")
Thread.sleep(forTimeInterval: 1) // Simulate work
semaphore.signal() // Increase semaphore value by 1. Unblocks waiting threads if any.
print("Task completed")
}
// You can launch multiple such blocks. Only 3 will run simultaneously.