线程的同步(四)---信号量

信号量内核对象用于对资源进行计数。它们与所有内核对象一样,包含一个使用数量,但是它们也包含另外两个带符号的32位值,一个是最大资源数量,一个是当前可用资源数量。最大资源数量用于标识信标能够控制的资源的最大数量,而当前资源数量则用于标识当前可以使用的资源的数量。

信号量的使用规则如下:
• 如果当前可用资源的数量大于0,则发出信标信号。
• 如果当前可用资源数量是0,则不发出信标信号。
• 系统决不允许当前可用资源的数量为负值。
• 当前可用资源数量决不能大于最大资源数量。

当使用信标时,不要将信号量对象的使用数量与它的当前资源数量混为一谈。

下面的函数用于创建信标内核对象:
HANDLE CreateSemaphore(
   PSECURITY_ATTRIBUTE psa,
   LONG lInitialCount,
   LONG lMaximumCount,
   PCTSTR pszName);
psa参数指定一个SECURITY_ATTRIBUTES结构,或传递零值,该参数定义了信号量的安全特性。
lInitialCount参数用于指明开始时(当前)这些资源中有多少可供使用。可设置0到lMaximumCount之间的一个值。
lMaximumCount参数用于告诉系统,应用程序处理的最大资源数量是多少。由于这是个带符号的32位值,因此最多可以拥有2147483647个资源。

pszName,指定信号量对象的名称。

当然,通过调用OpenSemaphore函数,另一个进程可以获得它自己的进程与现有信标相关的句柄:
HANDLE OpenSemaphore(
   DWORD fdwAccess,
   BOOL bInheritHandle,
   PCTSTR pszName);

通过调用ReleaseSemaphore函数,线程就能够对信标的当前资源数量进行递增:
BOOL ReleaseSemaphore(
   HANDLE hsem,
   LONG lReleaseCount,
   PLONG plPreviousCount);
该函数只是将lReleaseCount中的值添加给信标的当前可用资源数量。通常情况下,为lReleaseCount参数传递1,但是,不一定非要传递这个值。该函数也能够在它的*plPreviousCount中返回当前资源数量的原始值。实际上几乎没有应用程序关心这个值,因此可以传递NULL,将它忽略。

  以一个停车场的运作为例。简单起见,假设停车场只有三个车位,一开始三个车位都是空的。这时如果同时来了五辆车,看门人允许其中三辆直接进入,然后放下车拦,剩下的车则必须在入口等待,此后来的车也都不得不在入口处等待。这时,有一辆车离开停车场,看门人得知后,打开车拦,放入外面的一辆进去,如果又离开两辆,则又可以放入两辆,如此往复。
  在这个停车场系统中,车位是公共资源,每辆车好比一个线程,看门人起的就是信号量的作用。

  抽象的来讲,信号量的特性如下:信号量是一个非负整数(车位数),所有通过它的线程/进程(车辆)都会将该整数减一(通过它当然是为了使用资源),当该整数值为零时,所有试图通过它的线程都将处于等待状态。在信号量上我们定义两种操作: Wait(等待) 和 Release(释放)。当一个线程调用Wait操作时,它要么得到资源然后将信号量减一,要么一直等下去(指放入阻塞队列),直到信号量大于等于一时。Release(释放)实际上是在信号量上执行加操作,对应于车辆离开停车场,该操作之所以叫做“释放”是因为释放了由信号量守护的资源。


基本使用:
创建信号量:
HANDLE g_hSemaphore;  
g_hSemaphore = CreateSemaphore(NULL, 2, 3, NULL);//当前有2个资源可用,最多有3个资源可用

在线程中使用:

WaitForSingleObject(g_hSemaphore, INFINITE);//等待信号量>0  
。。。//资源的使用
ReleaseSemaphore(g_hSemaphore, 1, NULL);//信号量++  

使用完成要进行释放:
CloseHandle(g_hSemaphore);


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章