VC++ 线程同步之信号量(Semaphore)
信号量与互斥量类似,唯一的区别是多个对象可持有信号量的所有权。假设有一个复杂的数学运算要用到整个逻辑
CPU 核。如果每个核只运行一个线程,计算结果没问题,但是,如果每个核运行多个线程,计算结果就有问题
了。另外,还假设计算过程中所需的线程数量比同时工作的逻辑核的数量多。
最好选择信号量对象来处理这种情况,我们可以把信号量对象的最大值设置为机器的逻辑核数量。当线程数量不超
过核的数量时,它们能同时工作,优化计算过程。当线程数量超过逻辑核的数量时,一些线程将被挂起,等待其他
线程执行完毕。
每次只有一个线程可以获得互斥量,与此不同的是,只要未超过可持有信号量所有权的最大数量,信号量仍然处于
触发状态。如果一个线程要等待信号量,那么在其他线程释放信号量之前它将被挂起。
信号量涉及的函数:
创建或打开一个现有的信号量对象,可以使用CreateSemaphore:
HANDLE WINAPI CreateSemaphore(
LPSECURITY_ATTRIBUTES lpSemaphoreAttributes,
LONG lInitialCount,
LONG lMaximumCount,
LPCTSTR szName
);
第 1个参数是安全特征,可以指定也可以空出不填(如果不填,该参数将被设为默认值)。第 2个参数没置初始数目以确定信号量的初始触发状态。如果设置为 0,信号量为未触发状态。这个值必须小于第3个参数lMaxmumCount 的值。lMaxmumCount 表示可同时持有信号量所有权的最多对象(线程)数目。必须提供信号量名(szName)。
使用 OpenSemaphore 也可以打开一个现有的信号量:
HANDLE WINAPI OpenSemaphore(
DWORD dwDesiredAccess,
BOOl bInheritHandle,
LPCTSTR szName
);
如果信号量不存在,该例程将失败并返回 NULL。线程操作完毕后,必须释放信号量以递减计数器计数,这样其他
线程才能获得信号量。用 ReleaseSemaphore API 可以释放信号量:
BOOL WINAPI ReleaseSemaphore(
HANDLE hSemaphore,
LONG lReleaseCount,
LPLONG lpPreviousCount
);
这个API有3个参数。第1个参数是之前 CreateSemaphore 或 OpenSemaphore 返回的信号量的句柄。第2个参数
是信号量要递减的对象数量,其值通常是 1,因为线程总是逐个被释放的。有一种情况例外线程 A 获得一个信号
量,然后要创建也需要信号量的线程 B。线程A 在线程B 创建好之前完成了自己的任务,线程B不知道它将被强制
终止,所以线程A要终止子线程且递减信号量为2。
代码示例
以下是使用 Win32API 信号量实现的线程同步代码的完整 C++ 实现。该示例使用两个线程,一个线程在计算 1 到 100 的总和,另一个线程在计算 101 到 200 的总和。在两个线程完成计算后,主线程将这两个部分的总和相加并打印结果。

&spm=1001.2101.3001.5002&articleId=131336760&d=1&t=3&u=c57c30a5f02844388fd7928b4e4d313b)
8793

被折叠的 条评论
为什么被折叠?



