您的位置:首页 > 编程语言 > C语言/C++

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

2008-08-13 18:14 477 查看
  “信号量内核对象”用于对资源进行计数。

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

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

  可以使用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);

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: