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

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


当前回答

这是一个老问题,但信号量最有趣的用途之一是读/写锁,但没有明确提到。

r/w锁的工作方式很简单:为读取器消耗一个许可证,为写入器消耗所有许可证。 事实上,一个简单的r/w锁实现,但需要在读取时修改元数据(实际上是两次),这可能会成为瓶颈,但仍然比互斥锁或锁好得多。

另一个缺点是,写入也可以很容易地启动,除非信号量是公平的,或者写入在多个请求中获得许可,在这种情况下,它们之间需要一个显式的互斥。

进一步阅读:

其他回答

互斥:对资源的独占成员访问

信号量:对资源的n个成员访问

也就是说,互斥可以用来同步对计数器、文件、数据库等的访问。

信号量可以做同样的事情,但支持固定数量的同时调用者。例如,我可以将我的数据库调用包装在一个信号量(3)中,这样我的多线程应用程序将最多3个同时连接到数据库。所有的尝试都将被阻塞,直到三个插槽中的一个打开。它们让简单的节流变得非常简单。

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

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

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

这是一个老问题,但信号量最有趣的用途之一是读/写锁,但没有明确提到。

r/w锁的工作方式很简单:为读取器消耗一个许可证,为写入器消耗所有许可证。 事实上,一个简单的r/w锁实现,但需要在读取时修改元数据(实际上是两次),这可能会成为瓶颈,但仍然比互斥锁或锁好得多。

另一个缺点是,写入也可以很容易地启动,除非信号量是公平的,或者写入在多个请求中获得许可,在这种情况下,它们之间需要一个显式的互斥。

进一步阅读:

把信号量想象成夜总会的保镖。同时允许进入俱乐部的人数是固定的。如果俱乐部满了,任何人都不允许进入,但只要一个人离开,另一个人就可以进入。

它只是一种限制特定资源的消费者数量的方法。例如,限制应用程序中对数据库的同时调用数量。

下面是一个非常适合教学的c#例子:-)

using System;
using System.Collections.Generic;
using System.Text;
using System.Threading;

namespace TheNightclub
{
    public class Program
    {
        public static Semaphore Bouncer { get; set; }

        public static void Main(string[] args)
        {
            // Create the semaphore with 3 slots, where 3 are available.
            Bouncer = new Semaphore(3, 3);

            // Open the nightclub.
            OpenNightclub();
        }

        public static void OpenNightclub()
        {
            for (int i = 1; i <= 50; i++)
            {
                // Let each guest enter on an own thread.
                Thread thread = new Thread(new ParameterizedThreadStart(Guest));
                thread.Start(i);
            }
        }

        public static void Guest(object args)
        {
            // Wait to enter the nightclub (a semaphore to be released).
            Console.WriteLine("Guest {0} is waiting to entering nightclub.", args);
            Bouncer.WaitOne();          

            // Do some dancing.
            Console.WriteLine("Guest {0} is doing some dancing.", args);
            Thread.Sleep(500);

            // Let one guest out (release one semaphore).
            Console.WriteLine("Guest {0} is leaving the nightclub.", args);
            Bouncer.Release(1);
        }
    }
}

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

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