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

时间:2014-02-12 18:39:50

标签: mutex semaphore

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

6 个答案:

答案 0 :(得分:15)

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

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

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

答案 1 :(得分:9)

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

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

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

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

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

答案 2 :(得分:4)

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.   
  3. 资源管理。   在此使用方案中,计数值指示可用资源的数量。要获得对资源的控制,任务必须首先获得信号量 - 递减信号量计数值。当计数值达到零时,没有空闲资源。当任务完成资源时,它'返回'信号量 - 增加信号量计数值。在这种情况下,计数值最好等于创建信号量时的最大计数值。

  4.   

答案 3 :(得分:4)

我想你已经知道信号量是什么了,你只是想知道它是如何在“真实软件”中使用的。

“真的喜欢Office,Firefox有他们使用它的地方吗?”

是的,“真正的软件”使用信号量很多,它不仅仅是理论上的,例如Chromium source, windows semaphore handling code以及Virtual Box使用的相同代码。

“信号量的实际用途是什么”/“信号量的常用模式有哪些?”

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

Fuhrmanator reference典型的信号量使用是好的。

答案 4 :(得分:4)

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

短暂的一段时间后出现问题。并行执行的工作也使用了线程池。因此,如果我们在线程池上启动了太多任务,它们将使用整个池,然后等待它们的排队任务在线程池中获得一个插槽。

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

最后,Semaphore解决了这个问题。

答案 5 :(得分:3)

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

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