信号量如何工作?

信号量可以低于 0 吗?我的意思是,假设我有一个信号量N = 3,我调用“down”4次,然后N将保持0,但一个进程将被阻止?

反过来,如果一开始我打电话,N可以高于3吗?因为在我看来,如果N可以高于3,如果在开始时我调用了几次,那么稍后我可以调用比我能调用的次数更多,从而在关键部分放置更多的进程,那么信号量允许我。

如果有人能为我澄清一下,我将不胜感激。

格雷格


答案 1

(使用 java.util.concurrent.Semaphore 中的术语,给定 Java 标记。其中一些细节是特定于实现的。我怀疑你的“down”是Java信号量的方法,而你的“up”是.)acquire()release()

是的,您最后一次调用将阻塞,直到另一个线程调用或您的线程中断。acquire()release()

是的,您可以呼叫更多次,然后向下呼叫更多次数 - 至少使用 .release()java.util.concurrent.Semaphore

信号量的其他一些实现可能具有“最大”允许数的概念,并且调用超过该最大值的释放将失败。Java 类允许相反的情况,其中信号量可以从负数的允许开始,并且所有调用都将失败,直到有足够的调用。一旦许可证数量变为非负数,就再也不会变为负数。Semaphoreacquire()release()


答案 2

当值为 0 时向下调用应该不起作用。当它为3时调用确实有效。(我想到了Java)。

让我再补充一些。许多人认为锁像(二进制)信号量(即 - N = 1,所以信号量的值为0(持有)或1(不持有))。但这并不完全正确。锁具有“所有权”的概念,因此它可能是“可重入的”。这意味着持有锁的线程被允许再次调用lock()(有效地将计数从0移动到-1),因为线程已经持有锁并允许“重新输入”它。锁也可以是不可重入的。锁持有者调用 unlock() 的次数应与 lock() 相同。

信号量没有所有权的概念,因此它们不能是可重入的,尽管可以获得尽可能多的许可。这意味着线程在遇到值 0 时需要阻塞,直到有人递增信号量。

另外,在我所看到的(Java),你可以增加大于N的信号量,这也与所有权有关:信号量没有所有权的概念,所以任何人都可以给它更多的许可。与线程不同,每当线程在不持有锁定的情况下调用unlock()时,这都是一个错误。(在java中,它将引发异常)。

希望这种思考方式有所帮助。