《Windows via C/C++》学习笔记 —— 内核对象的“线程同步”之“信号量”

  “信号量内核对象”用于对资源进行计数。

  在信号量内核对象内部,和其他内核对象一样,有一个使用计数,该使用计数表示信号量内核对象被打开的次数。

  信号量内核对象中还有两个比较重要的数据,分别表示最大资源数和当前资源数。最大资源数表示能够管理的资源的总数,当前资源数表示目前可以被使用的资源数量。

 

  可以使用CreateSeamphore函数来创建一个信号量内核对象,该函数成功返回句柄,失败返回NULL。

HANDLE CreateSemaphore(
   PSECURITY_ATTRIBUTE psa,     
// 安全属性结构指针
   LONG lInitialCount,           // 初始可用资源数
   LONG lMaximumCount,           // 最大资源数
   PCTSTR pszName);              // 信号量内核对象的名字(NULL表示匿名)

 

  在Windows Vista中,提供了一个新的创建信号量内核对象的函数CreateSemaphoreEx,该函数成功返回句柄,失败返回NULL。

HANDLE CreateSemaphoreEx(
   PSECURITY_ATTRIBUTES psa,     
// 安全属性结构指针
   LONG lInitialCount,            // 初始可用资源数
   LONG lMaximumCount,       // 最大资源数
   PCTSTR pszName,           // 信号量内核对象的名字(NULL表示匿名)
   DWORD dwFlags,                // 保留型参数,应设置为0
   DWORD dwDesiredAccess);       // 访问限制(参看MSDN)

 

  同样,可以打开一个指定名称的信号量,使用OpenSemaphore函数:

HANDLE OpenSemaphore(
   DWORD dwDesiredAccess,     
// 访问限制(参看MSDN)
   BOOL bInheritHandle,        // 是否允许返回的句柄子进程被继承
   PCTSTR pszName);            // 指定的信号量名称

 

  假如,作为一个服务器,有一个缓冲区需要用来存放客户的连接请求,还有一个线程池用来处理连接。但是该缓冲区和线程池的大小有限,比如至多只能同时接纳和处理10位客户的连接请求,而当有10位客户请求连接而尚未处理完成的时候,此时一个新客户也试图建立连接,那么这个连接过程应该被推后,直到有一个连接处理完成之后,这个新客户的连接才能被处理。

  这个时候,可以使用信号量机制来处理线程同步的问题。

  当服务器初始化的时候,最大资源数为10,没有任何服务器请求连接,可以使用如下代码创建信号量内核对象:

HANDLE hSem  =  CreateSemaphore(NULL,  0 10 , NULL);

 

  该函数创建了一个信号量内核对象,最大资源数为10,当前可用资源数为0。由于当前可用资源数为0,所以调用WaitForSingleObject等这些等待函数来等待该信号量句柄的线程都会进入等待状态。

  这些等待函数在内部会查看信号量内核对象的可用资源数,如果该值大于0,则将其减1,线程保持可调度状态,这些比较和设置可用资源数是以原子过程进行的,所以是线程安全的。

  如果可用资源数等于0,则线程进入等待状态,当一个线程将信号量的可用资源数递增之后,某个或某些等待的线程就可以进入就绪状态。

  可以调用ReleaseSemaphore函数来让信号量内核对象的可用资源数递增:

 

BOOL ReleaseSemaphore(
   HANDLE hSemaphore,     
// 信号量内核对象句柄
   LONG lReleaseCount,        // 可用资源增加个数
   PLONG plPreviousCount);     // 返回上次可用资源的数量,一般传递NULL忽略之

 

  可惜的是,Windows没有提供一种方法让我们仅仅是查询当前信号量的可用资源数。

 

  自己总结了一下信号量使用的模型:

HANDLE g_hSem;      // 信号量句柄,在其他线程(比如主线程)中创建
DWORD WINAPI ThreadProc(PVOID pvParam)      // 线程函数
{
     
// 等待信号量,如果可用资源大于0,递减资源,线程继续运行,否则线程等待
     WaitForSingleObject(g_hSem, INFINITE);

     
// 访问资源

     
// 访问完毕,释放,递增可用资源数1个(可以根据需要递增n个)
     ReleaseSemaphore(g_hSem,  1 , NULL);
}

转载于:https://www.cnblogs.com/wz19860913/archive/2008/08/13/1267208.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值