信号量是一种编程概念,经常用于解决多线程问题。我对社区的问题是:
什么是信号量,如何使用它?
信号量是一种编程概念,经常用于解决多线程问题。我对社区的问题是:
什么是信号量,如何使用它?
当前回答
把信号量想象成夜总会的保镖。同时允许进入俱乐部的人数是固定的。如果俱乐部满了,任何人都不允许进入,但只要一个人离开,另一个人就可以进入。
它只是一种限制特定资源的消费者数量的方法。例如,限制应用程序中对数据库的同时调用数量。
下面是一个非常适合教学的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);
}
}
}
其他回答
这是一个老问题,但信号量最有趣的用途之一是读/写锁,但没有明确提到。
r/w锁的工作方式很简单:为读取器消耗一个许可证,为写入器消耗所有许可证。 事实上,一个简单的r/w锁实现,但需要在读取时修改元数据(实际上是两次),这可能会成为瓶颈,但仍然比互斥锁或锁好得多。
另一个缺点是,写入也可以很容易地启动,除非信号量是公平的,或者写入在多个请求中获得许可,在这种情况下,它们之间需要一个显式的互斥。
进一步阅读:
互斥:对资源的独占成员访问
信号量:对资源的n个成员访问
也就是说,互斥可以用来同步对计数器、文件、数据库等的访问。
信号量可以做同样的事情,但支持固定数量的同时调用者。例如,我可以将我的数据库调用包装在一个信号量(3)中,这样我的多线程应用程序将最多3个同时连接到数据库。所有的尝试都将被阻塞,直到三个插槽中的一个打开。它们让简单的节流变得非常简单。
信号量是一种锁定资源的方法,以保证在执行一段代码时,只有这段代码可以访问该资源。这可以防止两个线程并发访问一个资源,从而导致问题。
信号量也可以用作…信号量。 例如,如果有多个进程将数据排队到队列中,而只有一个任务使用队列中的数据。如果您不希望您的消费任务不断地轮询队列以获取可用数据,您可以使用信号量。
在这里,信号量不是用作排除机制,而是用作信号机制。 消费任务正在等待信号量 生产任务正在发送信号量。
这样,当且仅当有数据要退出队列时,消费任务才会运行
互斥量只是一个布尔值,而信号量是一个计数器。
两者都用于锁定部分代码,这样就不会有太多线程访问它。
例子
lock.set()
a += 1
lock.unset()
现在,如果lock是一个互斥锁,这意味着无论有多少线程尝试访问受保护的代码片段,它将始终处于锁定或解锁状态(表面下是一个布尔值)。当被锁定时,任何其他线程都会等待它被前一个线程解锁/取消设置。
现在想象一下,如果lock在引擎盖下是一个具有预定义MAX值的计数器(在我们的例子中是2)。然后,如果有两个线程试图访问该资源,那么lock的值将增加到2。如果第三个线程试图访问它,它就会等待计数器低于2,以此类推。
如果lock作为一个信号量的最大值为1,那么它将完全作为一个互斥量。