信号灯对象

信号灯对象是保持零和指定最大值之间的计数的同步对象。 每次线程完成等待信号灯对象时,计数都会递减,每次线程释放信号灯时计数都会递增。 当计数达到零时,没有更多的线程可以成功等待信号灯对象状态变为信号。 当信号量计数大于零时,会将信号量的状态设置为已发出信号;当信号量计数为零时,会将信号量的状态设置为未发出信号。

信号灯对象可用于控制可支持有限数量的用户的共享资源。 它充当一个入口,将共享资源的线程数限制为指定的最大数目。 例如,应用程序可能会限制其创建的窗口数。 它使用最大计数等于窗口限制的信号灯,每次创建窗口时递减计数,并在窗口关闭时递增。 应用程序在创建每个窗口之前,在调用其中一个 wait 函数 时指定信号灯对象。 当计数为零(指示已达到窗口限制)时,wait 函数将阻止执行窗口创建代码。

线程使用 CreateSemaphoreCreateSemaphoreEx 函数创建信号灯对象。 创建线程指定对象的初始计数和最大值。 初始计数不能小于零,也不能大于最大值。 创建线程还可以指定信号灯对象的名称。 其他进程中的线程可以通过在调用 OpenSemaphore 函数时指定其名称来打开现有信号灯对象的句柄。 有关互斥体、事件、信号灯和计时器对象的名称的其他信息,请参阅 进程间同步

如果多个线程正在一个信号灯上等待,则会选择一个等待的线程。 不要假设先入先出 (FIFO) 顺序。 外部事件(如内核模式 APC)可以更改等待顺序。

每当一个 等待函数 返回时,由于信号灯的状态设置为信号,信号灯的计数将减少 1。 ReleaseSemaphore 函数将信号灯的计数增加指定的量。 计数不能小于零或大于最大值。

信号灯的初始计数通常设置为最大值。 然后,随着受保护资源的消耗,计数将从该级别递减。 或者,可以创建初始计数为零的信号灯,以在初始化应用程序时阻止对受保护资源的访问。 初始化后,可以使用 ReleaseSemaphore 将计数递增到最大值。

拥有互斥对象的线程可以重复等待同一互斥对象成为信号,而不会阻止其执行。 但是,如果线程重复等待同一信号灯对象,则每次完成等待操作时都会递减信号灯的计数;当计数为零时,线程被阻止。 同样,只有拥有互斥体的线程才能成功调用 ReleaseMutex 函数,但任何线程都可以使用 ReleaseSemaphore 来增加信号灯对象的计数。

线程可以在调用任何 等待函数时重复指定同一信号灯对象,从而多次递减信号灯的计数。 但是,使用包含同一信号灯的多个句柄的数组调用其中一个多对象等待函数不会导致多次递减。

使用完信号灯对象后,调用 CloseHandle 函数以关闭句柄。 信号灯对象在其最后一个句柄已关闭时被销毁。 关闭句柄不会影响信号灯计数;因此,请确保在关闭句柄之前或进程终止之前调用 ReleaseSemaphore 。 否则,挂起的等待操作将超时或无限期地继续,具体取决于是否已指定超时值。

使用信号灯对象