您的位置:首页 > 其它

Chapter09-“内核模式下的线程同步”之信号量内核对象

2012-08-07 15:05 274 查看
信号量规则如下:

1. 如果当前资源计数大于0,信号量处于触发状态。

2. 如果当前资源计数等于0,信号量处于非触发状态。

3. 系统不允许当前资源计数为负数。

4. 当前资源计数不会比资源最大值还大。

一个线程通过调用一个等待函数(传递信号量对应的句柄作为参数)获取访问资源的权限。等待函数内部会检测信号量当前的资源计数,如果资源计数值等于0,则线程阻塞,处于等待状态;如果资源计数值大于0(即信号量处于触发状态),则计数减一之后当前调用的线程处于可调度状态。

有趣的是,信号量执行测试-设置(test-set)原子式(atomically)的操作。当你用一个信号量去请求资源时,操作系统检测资源是否可用和将可用资源数减一操作时中间不会被其他线程中断的,只有在资源计数减一之后,系统才允许其他线程去请求访问资源。

下面再介绍信号量(Semaphore)相关的函数:

1) 信号量创建函数——CreateSemaphore函数

HANDLE CreateSemaphore(

__in_optPSECURITY_ATTRIBUTE psa,

__in LONG lInitialCount,

__inLONG lMaximumCount,

__in_optPCTSTR pszName)

具体的函数说明请查看上面的MSDN链接。

信号量创建函数——CreateSemaphoreEX函数,可以指定想要的访问权限。

HANDLE CreateSemaphoreEx(

__in_opt PSECURITY_ATTRIBUTESpsa,

__inLONG lInitialCount,

__inLONG lMaximumCount,

__in_optPCTSTR pszName,

__reservedDWORD dwFlags,

__inDWORD dwDesiredAccess);

第一个参数psa指定了一些安全属性。

第二个参数lInitialCount指定了初始时可用的资源数。

第三个参数lMaximumCount指定了信号量(Semaphore)能够应用程序能够处理的最大资源数。

2) 打开信号量函数——OpenSemaphore函数

HANDLE OpenSemaphore(

__in DWORD dwDesiredAccess,

__inBOOL bInheritHandle,

__inPCTSTR pszName);

3) 增加信号量的当前计数函数——ReleaseSemphore函数

BOOL ReleaseSemaphore(

__in HANDLE hSemaphore,

__inLONG lReleaseCount,

__out_optPLONG plPreviousCount)

第一个参数hSemaphore是对应的信号量对象的句柄;

第二个参数lReleaseCount是要去增加的信号量计数个数;

第三个参数plPreviousCount,但函数成功后,该参数标记的是之前信号量的计数值。

一个示例:(代码转自此处

// 信号量对象句柄
HANDLE hSemaphore;
UINT ThreadProc15(LPVOID pParam)
{
 // 试图进入信号量关口
 WaitForSingleObject(hSemaphore, INFINITE);
 // 线程任务处理
 AfxMessageBox(" 线程一正在执行!");
 // 释放信号量计数
 ReleaseSemaphore(hSemaphore, 1, NULL);
 return 0;
}
UINT ThreadProc16(LPVOID pParam)
{
 // 试图进入信号量关口
 WaitForSingleObject(hSemaphore, INFINITE);
 // 线程任务处理
 AfxMessageBox(" 线程二正在执行!");
 // 释放信号量计数
 ReleaseSemaphore(hSemaphore, 1, NULL);
 return 0;
}
UINT ThreadProc17(LPVOID pParam)
{
 // 试图进入信号量关口
 WaitForSingleObject(hSemaphore, INFINITE);
 // 线程任务处理
 AfxMessageBox(" 线程三正在执行!");
 // 释放信号量计数
 ReleaseSemaphore(hSemaphore, 1, NULL);
 return 0;
}
……
void OnSemaphore()
{
 // 创建信号量对象
 hSemaphore = CreateSemaphore(NULL, 2, 2, NULL);
 // 开启线程
 AfxBeginThread(ThreadProc15, NULL);
 AfxBeginThread(ThreadProc16, NULL);
 AfxBeginThread(ThreadProc17, NULL);
}
略作分析:

step1:在OnSemaphore函数体内调用CreateSemaphore函数创建一个初始化值和最大值都为2的信号量(Semaphore),再分别开启三个使用信号量的线程

step2:每个线程内的代码结构相似,即先调用WaitforSingleObject函数等待信号量去获取对应的资源的访问权限,如果有可用资源,函数返回后,程序继续运行;如果没有可用资源,则线程一直阻塞等待。

step3:在线程访问完资源后,再调用ReleaseSemaphore函数增加信号量释放资源。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: