信号量

更新:2007 年 11 月

Semaphore 类表示一个命名信号量(系统范围)或本地信号量。Windows 信号量是计数信号量,可用于控制对资源池的访问。

管理受限资源

线程通过调用 WaitOne 方法来进入信号量,此方法是从 WaitHandle 类派生的。当调用返回时,信号量的计数将减少。当一个线程请求项而计数为零时,该线程会被阻止。当线程通过调用 Release 方法释放信号量时,将允许被阻止的线程进入。针对让被阻止的线程进入信号量,不存在保证的顺序(例如 FIFO 或 LIFO)。

线程可以通过重复调用 WaitOne 方法来多次进入信号量。若要释放信号量,线程可以调用 Release() 方法重载相同的次数,也可以调用 Release(Int32) 方法重载并指定要释放的项数。

信号量和线程标识

Semaphore 类不对向 WaitOneRelease 方法发出的调用强制线程标识。例如,信号量的一个常用方案包括一个生产者线程和一个使用者线程,其中一个线程总是增加信号量计数,而另一个线程总是减少信号量计数。

编程人员应负责确保线程释放信号量的次数不会过多。例如,假定信号量的最大计数为二,线程 A 和线程 B 都进入信号量。如果线程 B 中发生了一个编程错误,导致它调用 Release 两次,则两次调用都会成功。这样,信号量的计数就已经达到了最大值,所以,当线程 A 最终调用 Release 时,将引发 SemaphoreFullException

命名信号量

Windows 操作系统允许信号量具有名称。命名信号量在整个系统范围都有效。即,创建命名信号量后,所有进程中的所有线程都是可见的。因此,命名信号量可用于同步进程的活动以及线程的活动。

您可以使用可用于指定名称的一个构造函数来创建表示命名系统信号量的 Semaphore 对象。

说明:

因为命名信号量是针对整个系统范围的,所以可以具有多个表示同一命名信号量的 Semaphore 对象。每当调用构造函数或 OpenExisting 方法时,都会创建一个新的 Semaphore 对象。重复指定相同的名称将创建多个表示同一命名信号量的对象。

建议在使用命名信号量时要小心。因为命名信号量是针对整个系统范围的,所以使用同一名称的其他进程可能会意外地进入您的信号量。在同一计算机上执行的恶意代码可能以此作为一个切入点来发动拒绝服务攻击。

使用访问控制安全机制来保护表示命名信号量的 Semaphore 对象,最好通过使用可用于指定 SemaphoreSecurity 对象的构造函数来实施保护。您还可以使用 SetAccessControl 方法来应用访问控制安全,但这一做法会在信号量创建时间和信号量受保护时间之间留出一段漏洞时间。使用访问控制安全机制保护信号量可帮助阻止恶意攻击,但无法解决意外发生的名称冲突问题。

请参见

参考

Semaphore

其他资源

线程处理对象和功能