Java 信号量是如何工作的?

Java 信号量是如何工作的?,java,multithreading,computer-science,semaphore,Java,Multithreading,Computer Science,Semaphore,信号量是否可以低于0?我的意思是,假设我有一个N=3的信号量,我调用“down”4次,那么N将保持为0,但一个进程将被阻止 同样的,如果一开始我打电话,N能大于3吗?因为在我看来,如果N可以大于3,如果一开始我调用了几次,那么以后我可以调用更多的次,因此在关键部分放置更多的进程,然后信号量允许我 如果有人能为我澄清一下,我将不胜感激 Greg(使用java.util.concurrent.Semaphore中给定java标记的术语。其中一些细节是特定于实现的。我怀疑您的“down”是java信号

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

同样的,如果一开始我打电话,N能大于3吗?因为在我看来,如果N可以大于3,如果一开始我调用了几次,那么以后我可以调用更多的次,因此在关键部分放置更多的进程,然后信号量允许我

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

Greg

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

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

是的,您可以多次调用
release()
,然后再调用更多次-至少使用
java.util.concurrent.Semaphore


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

只需将N视为计算有限资源的计数器即可。由于资源的数量不能为负数,因此N仍然>=0。如果可用资源的数量发生变化,则也必须更改最大N。在任何其他情况下,我都不认为它是一个好的风格,而不首先递减它。

< P>是的,一个负值意味着你有等待信号量被释放的进程。正值意味着您可以在信号量阻塞之前多次调用acquire

你可以这样想:一个正数意味着有那么多可用的资源。负值意味着当所有资源都被占用时,许多实体需要一个资源。当你获得一个资源时,你会减少它的价值,当你释放它时,你会增加它的价值。如果减量后该值仍然>=0,则您将获得资源,否则您的实体将被放入队列

Wikipedia对信号量的一个很好的解释:

在0时调用不应该起作用。三点打电话也行。(我想到了Java)

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

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

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


希望这种方式有帮助。

< P>嗨,格雷戈考虑下面的例子:

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());
    }
如果您看到输出u,将得到以下结果:

Acquire : 0
Released : 1
Released : 2
Released : 3
Released : 4
Acquire : 3
Acquire : 2
Acquire : 1
Acquire : 0
等待还在继续

所以基本上许可证在每次发布时都会增加,acquire会减少到0。
一旦它达到0,它将等待直到对同一个对象调用release:)

使用
java.util.concurrent.Semaphore
方法
acquire()
release()
,我认为许可永远是
=0
。假设您希望同步线程,以便for循环中只能有1个线程。如果sem是初始值为1的
信号量类型,则这将不适用于超过2个线程

while(true){            

    sem.wait(); // wait is acquire

    for(int i=0; i<=5; i++){

        try {
            Thread.sleep(250);
        }catch (InterruptedException e) {}

        System.out.println("Thread "+ threadname+ " " + i);

             }
    sem.signal(); // signal is release }
while(true){
sem.wait();//wait是

对于(int i=0;iSee)来说,可以安全地说负信号量的作用类似于倒计时锁存器吗?实际上,当达到最后一个版本(count=0)时,我什么也做不了。或者有没有其他我想使用负信号量的用例?@jtkSource:我现在还不知道。
package yourpackage;

import java.util.concurrent.Semaphore;

public class SemaphoreLayer {
public Semaphore s=null;
public String name;
private int val;

public SemaphoreLayer(int i){
    s=new Semaphore(i); val=i;
}

public void wait(){
 try {
     val--;
     s.acquire();

  } catch (InterruptedException e) {
    System.out.println("Error signal semaphorelayer");
}}

public void signal(){
    if(val<0){val++;}{
        s.release();
        val++;
    }
}

}