我什么时候应该使用信号量?

发布于 2024-10-31 09:48:52 字数 86 浏览 1 评论 0原文

什么时候会使用信号量?

我能想到的唯一例子是限制同时访问相同数据/代码的线程数量...

信号量是最佳解决方案的任何其他场景吗?

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 ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

日久见人心 2024-11-07 09:48:52

信号量可能适合进程之间的信号传递。 对于多线程编程,应避免使用信号量。如果需要对资源进行独占访问,请使用互斥体。如果需要等待信号,请使用条件变量。

即使是最常提到的资源池情况,使用条件变量也可以比使用信号量更简单、更安全地实现。我们来看看这个案例。使用信号量的简单实现如下所示(伪代码):

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

第一个问题是信号量不能保护池不被多个线程访问。因此,需要另一种保护。让它成为一个锁:

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

需要采取额外的措施来确保访问时池不为空。从技术上讲,可以绕过信号量访问池,但这会破坏上述获取过程的资源可用性保证。因此该池只能通过该过程访问。

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

有了条件变量,这个问题就很容易解决了。这是阻塞获取的伪代码:

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

在这种情况下,添加非阻塞获取没有问题:

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

正如您所看到的,它甚至不需要访问条件变量,并且对阻塞情况没有任何损害。对我来说,它显然优于使用信号量。

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.

落花浅忆 2024-11-07 09:48:52

连接池。

即您有 20 个连接和 150 个线程。在这种情况下,您将有一个信号量来控制对 20 个连接的访问​​。

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.

枯叶蝶 2024-11-07 09:48:52

信号量可以由一个线程获取并在另一线程中释放。锁通常无法做到这一点。当线程 A 完成使用资源并将资源的控制权传递给线程 B 时,我使用了此方法。在这种特定情况下,我必须控制顺序以避免死锁。

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文