信号量如何工作?

14 java multithreading computer-science semaphore

信号量可以低于0吗?我的意思是,说我有一个N = 3的信号量,我称之为"向下"4次,然后N将保持为0,但是一个进程将被阻止?

而另一方面,如果在一开始我打电话,N可以高于3吗?因为正如我所看到的那样,如果在开始时N可以高于3,我会调用几次,然后我可以调用更多次,因此在关键部分放入更多进程然后信号量允许我.

如果有人为我澄清一点,我会非常感激.

格雷格

Jon*_*eet 18

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

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

是的,你可以打电话release()多次,然后打电话多次 - 至少是java.util.concurrent.Semaphore.

信号量的一些其他实现可能具有"最大"许可数量的概念,并且超出该最大值的释放调用将失败.Java Semaphore类允许相反的情况,其中信号量可以以负数许可开始,并且所有acquire()调用都将失败,直到有足够的release()调用.一旦许可证数量变为非负数,它将永远不会再次变为负数.


Pri*_*esh 8

嗨Greg考虑以下示例:

public static void main(String [] args) throws InterruptedException {

        Semaphore available = new Semaphore(1, true);

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.release();
        System.out.println("Released : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());

        available.acquire();
        System.out.println("Acquire : " +available.availablePermits());
    }
Run Code Online (Sandbox Code Playgroud)

如果你看到输出你会得到以下:

Acquire : 0
Released : 1
Released : 2
Released : 3
Released : 4
Acquire : 3
Acquire : 2
Acquire : 1
Acquire : 0
Run Code Online (Sandbox Code Playgroud)

等待正在进行中.

所以基本上许可将在每个版本上增加并且获取将减少它直到0.一旦它达到0它将等待直到在相同对象上调用release :)


Tom*_*Tom 6

当它为0时调用不应该工作.在3的时候调用它确实有效.(我在想Java).

让我再补充一点.许多人会想到像(二进制)信号量这样的锁(即 - N = 1,因此信号量的值为0(保持)或1(不保持)).但这不太对.锁具有"所有权"的概念,因此它可能是"可重入的".这意味着一个持有锁的线程被允许再次调用lock()(有效地将计数从0移动到-1),因为线程已经持有锁并被允许"重新进入"它.锁也可以是不可重入的.锁定持有者应该与lock()调用unlock()的次数相同.

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

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

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