信号量的实际用途是什么?

NoS*_*tAl 18 mutex semaphore

非二进制的..
我从未遇到过要求我使用信号量而不是互斥量的问题.那么这主要是理论上的构造,还是像Office这样的真实流行,Firefox有哪些地方可以使用它?如果是这样,信号量的常用模式是什么?

Bob*_*ish 16

非二进制信号量用于资源分配.信号量可能包含特定资源的数量.

如果您有一个连接池(例如Web浏览器可能使用),则单个线程可以通过等待信号量来获取连接来保留池的成员,使用该连接,然后通过释放信号量来释放连接.

您可以通过创建计数器然后在计数器周围建立互斥区域来模拟信号量.但是,等待上面的资源需要两级互斥,并且不如使用信号量那么优雅.


Han*_*ant 10

信号量可以计算.计数基本上是线程不安全的,它是处理器上的读 - 修改 - 写操作,因此不是原子的.有一些较小的原语可供安全计数,Interlocked.Increment()是原子的.但是,原子性是一个相当弱的线程原语,在许多情况下,当计数处于临界值时,你还必须阻塞代码.

0为"关键",所有资源都已使用.一个标准的例子是倒计时处理器内核以运行线程,一旦你全部使用它们,你就不应该启动另一个线程,直到其中一个完成并且不再需要处理器内核.尽可能基本.

二元信号量经常出现在有关线程的文献中.标准的教科书条目,与荷兰人Edsger Dijkstra密切相关.计算机科学的先驱,在20世纪60年代首次开始考虑如何让处理器运行多个程序.他的P和V注释只对像我这样的荷兰语说话者有意义.Parkeer和Vrij是你试图把你的车放在某个地方时使用的术语:)很久以前,每个人都开始考虑使用不同类型的线程原语,如互斥和监视器.只需要支持信号量的原语,一旦你得到二进制信号量,那么你就做其他所有事情.在基础设施之上构建抽象,组合在软件中的工作方式.

稍微涂了一点,我正在滚动,有一件事让Semaphore与其他原语如Mutex和Monitor完全不同而且锁定是它没有线程亲和力.当您编写线程代码时,这是一个相当大的问题,您尝试实现的通常合同是只有一个线程可以同时访问资源.所有其他.NET同步对象都是可重入的,您不能通过在同一个线程上多次锁定来使自己陷入僵局.它们非常友好,只需在获得锁定时递增计数器.当你释放时再次倒计时.并且只有在计数达到0时才放弃锁定.信号量根本不起作用,无论哪个线程获得它,它都会计算.在某些情况下真的很重要,比如我前面引用的count-down-the-thread-resources示例.

真的是有用的.不太常见.监视器是线程的瑞士军刀,这就是为什么它有自己的关键字.C#中的lock关键字,VB.NET中的SyncLock


Edg*_*lho 7

我认为您已经知道信号量是什么,您只是想知道它如何在“真实软件”上使用。

“像 Office、Firefox 这样的真正软件有使用它的地方吗?”

是的,“真正的软件”大量使用信号量,这不仅仅是理论上的,例如Chromium 源、Windows 信号量处理代码和Virtual Box使用的相同代码。

“信号量的实际用途是什么”/“信号量的常见使用模式是什么?”

它们更适合生产者-消费者同步问题。生产者和消费者的数量> 1 的情况。

Fuhrmanator对信号量典型使用的参考是很好的。


Luk*_*uke 6

一个可能的实际示例可能是固定线程池:您不想浪费所有系统资源,因此在特定时间只允许执行特定数量的线程;所有剩余的线程将在队列中等待。

现在,我怀疑例如 Java 线程池是使用像信号量这样的裸资源实现的,但是无论使用什么同步构造,它在理论上都是等效的。您可以在此处获得有关 Java 线程池(和固定线程池)的完整说明:http : //docs.oracle.com/javase/tutorial/essential/concurrency/pools.html


Gru*_*nik 6

我在生产环境中使用了几次信号量。运行 Windows 服务,它将获得要执行的任务列表。这些任务都可以并行运行。因此,我们最初只是将它们全部放入 .net 线程池中,并将它们设置为运行。

不久之后,问题就出现了。并行执行的工作也使用线程池。所以如果我们在线程池上启动了太多任务,它们会消耗整个池,然后等待他们排队的任务在线程池中获得一个槽。

泄漏的解决方案是只保留一个共享计数器,任务会在它们继续运行时递增和递减它。这工作了一段时间,但最终该服务将停止执行任何操作。重复的竞争条件导致计数器显示线程池中所有允许的插槽都被占用,即使没有任何东西在运行。

最后一个信号量解决了这个问题。


Fuh*_*tor 5

http://www.cs.wustl.edu/~schmidt/win32-cv-1.html第2.2节中引用Doug Schmidt :

计数信号量是一种同步机制,通常用于序列化或协调多个控制线程。从概念上讲,计数信号量是非负整数,可以按原子方式递增和递减。如果一个线程试图减少其值为0的信号量,则该线程将被挂起,等待另一个线程将信号量计数增加到0以上。

计数信号量通常用于跟踪进程中多个线程共享的对象状态的变化。例如,他们可以记录特定事件的发生。与条件变量不同,信号量保持状态。因此,即使事件已在过去发生,它们也允许线程基于此状态做出决策。

至于模式,根据http://www.freertos.org/Real-time-embedded-RTOS-Counting-Semaphores.html,有两种

计数信号量通常用于两件事:

  1. 计数事件。在这种使用情况下,事件处理程序将在每次事件发生时“给出”信号量(增加信号量计数值),而处理程序任务将在每次处理事件时“获得”信号量(减小信号量计数值)。因此,计数值是已发生的事件数与已处理的事件数之间的差。在这种情况下,希望在创建信号量时将计数值设为零。

  2. 资源管理。在这种使用情况下,计数值指示可用资源的数量。为了获得对资源的控制,任务必须首先获得一个信号量-减少信号量计数值。当计数值达到零时,将没有可用资源。当任务使用资源完成时,它将“给予”信号量-增加信号量计数值。在这种情况下,希望在创建信号量时使计数值等于最大计数值。