信号量是一种编程概念,经常用于解决多线程问题。我对社区的问题是:

什么是信号量,如何使用它?


当前回答

互斥量只是一个布尔值,而信号量是一个计数器。

两者都用于锁定部分代码,这样就不会有太多线程访问它。

例子

lock.set()
a += 1
lock.unset()

现在,如果lock是一个互斥锁,这意味着无论有多少线程尝试访问受保护的代码片段,它将始终处于锁定或解锁状态(表面下是一个布尔值)。当被锁定时,任何其他线程都会等待它被前一个线程解锁/取消设置。

现在想象一下,如果lock在引擎盖下是一个具有预定义MAX值的计数器(在我们的例子中是2)。然后,如果有两个线程试图访问该资源,那么lock的值将增加到2。如果第三个线程试图访问它,它就会等待计数器低于2,以此类推。

如果lock作为一个信号量的最大值为1,那么它将完全作为一个互斥量。

其他回答

信号量也可以用作…信号量。 例如,如果有多个进程将数据排队到队列中,而只有一个任务使用队列中的数据。如果您不希望您的消费任务不断地轮询队列以获取可用数据,您可以使用信号量。

在这里,信号量不是用作排除机制,而是用作信号机制。 消费任务正在等待信号量 生产任务正在发送信号量。

这样,当且仅当有数据要退出队列时,消费任务才会运行

@Craig:

信号量是一种锁定 资源,这样才有保证 当执行一段代码时, 只有这段代码可以访问 该资源。这保留了两个线程 从并发访问资源, 这可能会导致问题。

这不仅仅局限于一个线程。信号量可以配置为允许固定数量的线程访问资源。

信号量的作用类似于线程限制器。

示例:如果您有一个100个线程的池,并且您想执行一些DB操作。如果在给定的时间有100个线程访问数据库,那么在数据库中可能会有锁定问题,所以我们可以使用信号量,一次只允许有限的线程。下面的例子一次只允许一个线程。当一个线程调用acquire()方法时,它将获得访问权限,在调用release()方法后,它将释放访问权限,以便下一个线程获得访问权限。

    package practice;
    import java.util.concurrent.Semaphore;

    public class SemaphoreExample {
        public static void main(String[] args) {
            Semaphore s = new Semaphore(1);
            semaphoreTask s1 = new semaphoreTask(s);
            semaphoreTask s2 = new semaphoreTask(s);
            semaphoreTask s3 = new semaphoreTask(s);
            semaphoreTask s4 = new semaphoreTask(s);
            semaphoreTask s5 = new semaphoreTask(s);
            s1.start();
            s2.start();
            s3.start();
            s4.start();
            s5.start();
        }
    }

    class semaphoreTask extends Thread {
        Semaphore s;
        public semaphoreTask(Semaphore s) {
            this.s = s;
        }
        @Override
        public void run() {
            try {
                s.acquire();
                Thread.sleep(1000);
                System.out.println(Thread.currentThread().getName()+" Going to perform some operation");
                s.release();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        } 
    }

假设一辆出租车可以容纳3人(后面)+2人(前面),包括司机。因此,一个信号量一次只允许5个人在一辆车里。 互斥只允许一个人坐在汽车的一个座位上。

因此,互斥量是允许对资源的独占访问(如操作系统线程),而信号量是允许在同一时间访问n个资源。

信号量是一个包含自然数(即大于或等于零的整数)的对象,在自然数上定义了两个修改操作。一个运算V,给自然数加1。另一个操作,P,将自然数减少1。这两个活动都是原子的(即没有其他操作可以与V或P同时执行)。

因为自然数0不能减少,所以在包含0的信号量上调用P将阻塞调用进程(/thread)的执行,直到该数字不再为0,P可以成功(原子地)执行为止。

正如在其他回答中提到的,信号量可用于将对某个资源的访问限制为最大(但可变的)进程数。