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

本文深入探讨了Windows操作系统中信号量的工作原理、关键函数及其应用实例,包括信号量的创建、打开、计数增加和减少的过程,以及如何在多线程环境下合理使用信号量来控制资源访问。

信号量规则如下:

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函数增加信号量释放资源。

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值