When would one use semaphores ?
Only example I can think of is limiting the number of threads accessing the same data/code simultaneously...
Any other scenarios in which semaphores would be the best solution ?
Semaphores are typically used in one of two ways: To control access to a shared device between tasks. A printer is a good example. You don't want 2 tasks sending to the printer at once, so you create a binary semaphore to control printer access.
The main aim of using a semaphore is process synchronization and access control for a common resource in a concurrent environment. The initial value of a semaphore depends on the problem at hand. Usually, we use the number of resources available as the initial value.
If you have number of instances for resource it is better to use Binary semaphore. If you have single instance for resource it is better to use mutex.
Semaphores are used to solve a problem of race condition, mutual exclusion, process synchronization.
Connection Pools.
I.e. you have 20 connections and 150 threads. In that case you would have a semaphore to control access to the 20 connections.
Semaphores might be appropriate for signaling between processes. For multithreaded programming, semaphores should be avoided. If you need exclusive access to a resource, use mutex. If you need to wait for a signal, use condition variable.
Even the most often mentioned case of a resource pool can be implemented simpler and safer with a condition variable than with a semaphore. Let's look at this case. A naive implementation with a semaphore would look like (pseudocode):
wait for semaphore to open
take a resource out of the pool
use the resource
put it back to the pool
open the semaphore for one more thread
The first problem is that semaphore does not protect the pool from being accessed by several threads. So, another protection is required. Let it be a lock:
wait for semaphore to open
acquire the lock for the pool
take a resource out of the pool
release the lock
use the resource
acquire the lock
put the resource back to the pool
release the lock
open the semaphore for one more thread
Additional measures need to be taken to ensure the pool is not empty when accessed. Technically it is possible to access the pool bypassing the semaphore, but it would break resource availability guarantees for the acquisition procedure above. So the pool should be only accessed via that procedure.
So far so good, but what if a thread does not want to wait passively for a resource? Can non-blocking resource acquisition be supported? It's easy if the semaphore itself supports non-blocking acquisition; otherwise (e.g. on Windows) this will be problematic. The semaphore cannot be bypassed, because it would break the blocking case. Passing through the semaphore only if the pool is not empty may lead to a deadlock if done under the lock, but as soon as the lock is released, the result of the check for emptiness becomes useless. It is probably doable (I did not try), but surely leads to significant additional complexity.
With condition variable, this is solved easily. Here is the pseudocode with blocking acquisition:
acquire the lock
while the resource pool is empty,
wait for condition variable to be signaled
take a resource out of the pool
release the lock
use the resource
acquire the lock
put the resource back to the pool
release the lock
signal the condition variable
And in this case there is no problem to add non-blocking acquisition:
acquire the lock
if the resource pool is not empty,
take a resource out of the pool
release the lock
if the pool was empty, return
As you may see, it does not even need to access condition variable, and makes no harm to the blocking case. To me, it's clearly superior to the use of semaphore.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With