什么时候应该使用信号量? [英] When should I use semaphores?

查看:559
本文介绍了什么时候应该使用信号量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一个人何时会使用信号量?

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 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.

到目前为止很好,但是如果线程不想被动地等待资源怎么办?可以支持非阻塞资源获取吗?如果信号量本身支持无阻塞获取,这很容易.否则(例如在Windows上),这将是有问题的.无法绕过信号量,因为它会破坏阻塞情况.仅当池不为空时才通过信号量,如果在锁下进行操作,则可能导致死锁,但是一旦释放锁,空检查的结果就变得无用了.这可能是可行的(我没有尝试过),但是肯定会导致额外的复杂性.

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.

这篇关于什么时候应该使用信号量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆