Windows 信号量(Semaphore)笔记
1. 基本概念
信号量是用于资源计数的内核对象,用于控制多个线程对共享资源的访问。
1.1 信号量的状态
| 状态 |
含义 |
| 有信号状态(触发状态) |
当前资源计数 > 0,表示有可用资源 |
| 无信号状态(未触发状态) |
当前资源计数 = 0,表示没有可用资源 |
1.2 信号量的组成
| 成员 |
说明 |
| 计数器 |
该内核对象被使用的次数 |
最大资源数量(lMaximumCount) |
信号量可以控制的最大资源数量(带符号的32位),即计数器的上限值 |
当前资源数量(lInitialCount) |
标识当前可用资源的数量(带符号的32位)。表示当前开放资源的个数,只有开放的资源才能被线程所申请 |
注意:lInitialCount 表示的是当前可用资源的数量,而非剩余资源的数量。每次线程成功等待信号量,当前资源计数减 1;每次调用 ReleaseSemaphore,当前资源计数增加指定的数量。
2. 核心 API
2.1 创建信号量:CreateSemaphoreW
1 2 3 4 5 6 7 8
| HANDLE WINAPI CreateSemaphoreW( _In_opt_ LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, _In_ LONG lInitialCount, _In_ LONG lMaximumCount, _In_opt_ LPCWSTR lpName );
|
参数说明:
| 参数名 |
含义 |
| lpSemaphoreAttributes |
安全属性(NULL = 默认,句柄不可继承) |
| lInitialCount |
初始可用资源数量(0 = 无信号状态;>0 = 有信号状态),不能超过 lMaximumCount |
| lMaximumCount |
信号量计数的最大值(即最大资源数量) |
| lpName |
信号量名称(NULL = 匿名信号量) |
2.2 释放信号量:ReleaseSemaphore
1 2 3 4 5 6 7 8
| WINBASEAPI BOOL WINAPI ReleaseSemaphore( _In_ HANDLE hSemaphore, _In_ LONG lReleaseCount, _Out_opt_ LPLONG lpPreviousCount );
|
3. 代码示例
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| static HANDLE semOne; static HANDLE semTwo; static int num;
DWORD WINAPI Read(void* arg) { while (TRUE) { fputs("\nRead\n", stdout); WaitForSingleObject(semTwo, INFINITE); printf("begin read: "); scanf("%d", &num); ReleaseSemaphore(semOne, 1, NULL); } return 0; } DWORD WINAPI Accu(void* arg) { while (TRUE) { fputs("\nAccu\n", stdout); WaitForSingleObject(semOne, INFINITE); printf("begin accu: "); scanf("%d", &num); ReleaseSemaphore(semTwo, 1, NULL); } return 0; }
int main() { WINBASEAPI BOOL WINAPI ReleaseSemaphore( _In_ HANDLE hSemaphore, _In_ LONG lReleaseCount, _Out_opt_ LPLONG lpPreviousCount );
HANDLE hThread1, hThread2; semOne = CreateSemaphore(NULL, 0, 1, NULL); semTwo = CreateSemaphore(NULL, 1, 1, NULL); hThread1 = CreateThread(NULL, 0, Read, NULL, 0, NULL); hThread2 = CreateThread(NULL, 0, Accu, NULL, 0, NULL); WaitForSingleObject(hThread1, INFINITE); WaitForSingleObject(hThread2, INFINITE); CloseHandle(semOne); CloseHandle(semOne); return 0; }
|