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

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


当前回答

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

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

其他回答

想象一下,每个人都想上厕所而浴室的钥匙是有限的。如果剩下的钥匙不够多,那个人就需要等待。因此,可以将信号量看作是表示不同进程(上厕所的人)可以请求访问的卫生间(系统资源)可用的一组键。

现在想象一下两个过程同时去洗手间。这不是一个好的情况,信号量被用来防止这种情况。不幸的是,信号量是一种自愿机制,进程(我们的上厕所的人)可以忽略它(即,即使有钥匙,有人仍然可以把门踢开)。

二进制/互斥量和计数信号量之间也有区别。

请登录http://www.cs.columbia.edu/~jae/4118/lect/L05-ipc.html查看课堂讲稿。

硬件或软件标志。在多任务系统中,信号量是一个变量,其值表示公共资源的状态。需要资源的进程检查信号量以确定资源状态,然后决定如何继续。

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

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

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

示例:如果您有一个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();
            }
        } 
    }

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

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

例子

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

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

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

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