2024年3月14日发(作者:)

信号量(Semaphore)内核对象对线程的同步方式与前面几种方法不同,它允许多个

线程在同一时刻访问同一资源,但是需要限制在同一时刻访问此资源的最大线程数目。在

用CreateSemaphore()创建信号量时即要同时指出允许的最大资源计数和当前可用资

源计数。一般是将当前可用资源计数设置为最大资源计数,每增加一个线程对共享资源的

访问,当前可用资源计数就会减1,只要当前可用资源计数是大于0的,就可以发出信号

量信号。但是当前可用计数减小到0时则说明当前占用资源的线程数已经达到了所允许的

最大数目,不能在允许其他线程的进入,此时的信号量信号将无法发出。线程在处理完共

享资源后,应在离开的同时通过ReleaseSemaphore()函数将当前可用资源计数加1。

在任何时候当前可用资源计数决不可能大于最大资源计数。

信号量是通过计数来对线程访问资源进行控制的,而实际上信号量确实也被称作

Dijkstra计数器。

使用信号量内核对象进行线程同步主要会用到CreateSemaphore()、

OpenSemaphore()、ReleaseSemaphore()、WaitForSingleObject()和

WaitForMultipleObjects()等函数。其中,CreateSemaphore()用来创建一个信号

量内核对象,其函数原型为:

HANDLE CreateSemaphore(

LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, // 安全属性指针

LONG lInitialCount, // 初始计数

LONG lMaximumCount, // 最大计数

LPCTSTR lpName // 对象名指针

);

参数lMaximumCount是一个有符号32位值,定义了允许的最大资源计数,最大取

值不能超过4294967295。lpName参数可以为创建的信号量定义一个名字,由于其创建

的是一个内核对象,因此在其他进程中可以通过该名字而得到此信号量。OpenSemaphore

()函数即可用来根据信号量名打开在其他进程中创建的信号量,函数原型如下:

HANDLE OpenSemaphore(

DWORD dwDesiredAccess, // 访问标志

BOOL bInheritHandle, // 继承标志

LPCTSTR lpName // 信号量名

);

在线程离开对共享资源的处理时,必须通过ReleaseSemaphore()来增加当前可用

资源计数。否则将会出现当前正在处理共享资源的实际线程数并没有达到要限制的数值,

而其他线程却因为当前可用资源计数为0而仍无法进入的情况。ReleaseSemaphore()

的函数原型为:

BOOL ReleaseSemaphore(