开发者

When should I use semaphores?

开发者 https://www.devze.com 2023-02-23 07:17 出处:网络
When would one use semaphores ? Only example I can think of is limiting the number of threads accessing t开发者_JS百科he same data/code simultaneously...

When would one use semaphores ?

Only example I can think of is limiting the number of threads accessing t开发者_JS百科he same data/code simultaneously...

Any other scenarios in which semaphores would be the best solution ?


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.


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 can be acquired by one thread and released in another. Locks typically cannot do this. I have used this when thread A finishes using a resource and passes control of the resource to thread B. I had to control the order to avoid deadlocks in this particular situation.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号