如果你已经了解信号量(Semaphore)的概念了,请跳过这一段。
信号量(Semaphore)是在多线程环境下使用的一种设施, 它负责协调各个线程, 以保证它们能够正确、合理的使用公共资源。
我们来看看一个停车场是怎样运作的。为了简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这是如果同时来了五辆车,看门人允许其中三辆不受阻碍的进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入一辆,如果又离开两辆,则又可以放入两辆,如此往复。
在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。
更进一步,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。 当一个线程调用Wait等待)操作时,它要么通过然后将信号量减一,要么一自等下去,直到信号量大于一或超时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是应为加操作实际上是释放了由信号量守护的资源。(引自:)
NET Framework 类库
注意:此类在 .NET Framework 2.0 版中是新增的。
限制可同时访问某一资源或资源池的线程数。
命名空间:System.Threading
程序集:System(在 system.dll 中)[ComVisibleAttribute(false)]public sealed class Semaphore : WaitHandle
注意 |
---|
应用于此类的 属性 (Attribute) 具有下面的 属性 (Property) 值: | 。 HostProtectionAttribute 不影响桌面应用程序(桌面应用程序一般通过双击图标,键入命令或在浏览器中输入 URL 启动)。有关更多信息, 请参见 HostProtectionAttribute 类或 。 |
使用 Semaphore 类可控制对资源池的访问。线程通过调用 方法(从 类继承)进入信号量,并通过调用 方法释放信号量。
信号量的计数在每次线程进入信号量时减小,在线程释放信号量时增加。当计数为零时,后面的请求将被阻塞,直到有其他线程释放信号量。当所有的线程都已释放信号量时,计数达到创建信号量时所指定的最大值。
被阻止的线程并不一定按特定的顺序(如 FIFO 或 LIFO)进入信号量。
线程可通过重复调用 WaitOne 方法多次进入信号量。为释放这些入口中的部分或全部,线程可多次调用无参数的 方法重载,也可以调用 方法重载来指定要释放的入口数。
Semaphore 类不对 WaitOne 或 Release 调用强制线程标识。程序员负责确保线程释放信号量的次数不能太多。例如,假定信号量的最大计数为 2,并且线程 A 和线程 B 同时进入信号量。如果线程 B 中的编程错误导致它两次调用 Release,则两次调用都成功。这样,信号量的计数已满,当线程 A 最终调用 Release 时便会引发 。
信号量分为两种类型:局部信号量和已命名的系统信号量。如果您使用接受名称的构造函数创建 Semaphore 对象,则该对象与具有该名称的操作系统信号量关联。已命名的系统信号量在整个操作系统中都可见,可用于同步进程活动。您可以创建多个 Semaphore 对象来表示同一个已命名的系统信号量,也可以使用 方法打开现有的已命名系统信号量。
局部信号量仅存在于您的进程内。您的进程中任何引用局部 Semaphore 对象的线程都可以使用它。每个 Semaphore 对象都是一个单独的局部信号量。
下面的代码示例创建一个最大计数为 3、初始计数为 0 的信号量。该示例启动五个线程,这些线程阻止该信号量的等待。主线程使用 Release(Int32) 方法重载,以便将信号量计数增加为其最大值,从而允许三个线程进入该信号量。每个线程都使用 方法等待一秒钟以便模拟工作,然后调用 Release 方法重载以释放信号量。每次释放信号量时,都显示前一个信号量计数。控制台消息对信号量的使用进行跟踪。每个线程的模拟工作间隔都稍有增加,以使输出更为易读。