用内核对象进行线程同步——信号量内核对象
2017-08-09 19:03
246 查看
信号量内核对象包含一个使用计数,还有另外俩个32位值:一个最大资源计数,一个当前资源计数。
最大资源计数表示信号量可以控制的最大资源数量,即可以同时调度的最大线程数;当前资源计数表示信号量当前可用资源的数量,即当前可调度的线程数。
信号量规则:
1. 当前资源计数 > 0, 信号量处于触发状态
2. 当前资源计数 = 0, 信号量处于未触发状态
3. 系统绝不会让当前资源计数 < 0
4. 系统绝不会让当前资源计数 > 最大资源计数
创建信号量内核对象
打开信号量内核对象
递增信号量内核对象
案例1
案例2
最后输出结果为:
ReleaseSemaphore error
10
11
12
13
14
0
0
0
0
0
ReleaseSemaphore error
10
11
12
13
14
15
16
17
0
0
最大资源计数表示信号量可以控制的最大资源数量,即可以同时调度的最大线程数;当前资源计数表示信号量当前可用资源的数量,即当前可调度的线程数。
信号量规则:
1. 当前资源计数 > 0, 信号量处于触发状态
2. 当前资源计数 = 0, 信号量处于未触发状态
3. 系统绝不会让当前资源计数 < 0
4. 系统绝不会让当前资源计数 > 最大资源计数
创建信号量内核对象
HANDLE CreateSemaphore( LPSECURITY_ATTRIBUTES lpSemaphoreAttributes, LONG lInitialCount, // 当前资源计数 LONG lMaximumCount, // 最大资源计数 LPCSTR lpName );
打开信号量内核对象
HANDLE OpenSemaphore( DWORD dwDesiredAccess, BOOL bInheritHandle, LPCSTR lpName );
递增信号量内核对象
BOOL ReleaseSemaphore( HANDLE hSemaphore, LONG lReleaseCount, // lReleaseCount + 当前资源计数 = 新的当前资源计数 LPLONG lpPreviousCount );
案例1
#include "stdafx.h" #include <windows.h> #include <process.h> #include <iostream> using namespace std; HANDLE h_Semaphore; long* pLong = NULL; UINT WINAPI ThreadFunc1(PVOID pArguments) { // 等待函数如果发现信号量的当前资源计数为0(信号量处于未触发状态),则线程进入等待状态 // 如果信号量的当前资源计数不为0(信号量处于触发状态),当前资源计数减1,线程进入可调度状态 WaitForSingleObject(h_Semaphore, INFINITE); Sleep(10000); cout << "ThreadFunc1.." << endl; // 结束对资源的访问后,调用ReleaseSemaphore对当前资源计数加1 ReleaseSemaphore(h_Semaphore, 1, pLong); _endthreadex(0); return 0; } UINT WINAPI ThreadFunc2(PVOID pArguments) { WaitForSingleObject(h_Semaphore, INFINITE); Sleep(10000); cout << "ThreadFunc2.." << endl; ReleaseSemaphore(h_Semaphore, 1, pLong); _endthreadex(0); return 0; } UINT WINAPI ThreadFunc3(PVOID pArguments) { WaitForSingleObject(h_Semaphore, INFINITE); Sleep(10000); cout << "ThreadFunc3.." << endl; ReleaseSemaphore(h_Semaphore, 1, pLong); _endthreadex(0); return 0; } UINT WINAPI ThreadFunc4(PVOID pArguments) { WaitForSingleObject(h_Semaphore, INFINITE); int n = 0; Sleep(10000); cout << "ThreadFunc4.." << endl; ReleaseSemaphore(h_Semaphore, 1, pLong); _endthreadex(0); return 0; } UINT WINAPI ThreadFunc5(PVOID pArguments) { WaitForSingleObject(h_Semaphore, INFINITE); Sleep(10000); cout << "ThreadFunc5.." << endl; ReleaseSemaphore(h_Semaphore, 1, pLong); _endthreadex(0); return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE handle[5]; unsigned unThreadID[5]; // 创建一个信号量 // 当前资源计数器被初始化为0,信号量没有被触发 // 最大资源计数为3 h_Semaphore = CreateSemaphore(NULL, 0, 5, NULL); handle[0] = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc1, NULL, 0, &unThreadID[0]); handle[1] = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc2, NULL, 0, &unThreadID[1]); handle[2] = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc3, NULL, 0, &unThreadID[2]); handle[3] = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc4, NULL, 0, &unThreadID[3]); handle[4] = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc5, NULL, 0, &unThreadID[4]); // 递增信号量的当前资源计数为5(0+5=5) // 当前资源计数大于0时,触发了信号量,此时可以同时调度2个等待该信号量的线程,其余线程继续等待 ReleaseSemaphore(h_Semaphore, 5, NULL); getchar(); CloseHandle(h_Semaphore); return 0; }
案例2
// ThreadDemo.cpp : コンソール アプリケーションのエントリ ポイントを定義します。 // #include "stdafx.h" #include <windows.h> #include <process.h> #include <iostream> using namespace std; HANDLE h_Semaphore; long* pLong = NULL; int g_Data[10] = { 0 }; UINT WINAPI ThreadFunc(PVOID pArguments) { WaitForSingleObject(h_Semaphore, INFINITE); WaitForSingleObject(h_Semaphore, INFINITE); WaitForSingleObject(h_Semaphore, INFINITE); _endthreadex(0); return 0; } int _tmain(int argc, _TCHAR* argv[]) { HANDLE handle; unsigned unThreadID; int i = 0; // 创建一个信号量 // 当前资源计数器被初始化为0,信号量没有被触发 // 最大资源计数为5 h_Semaphore = CreateSemaphore(NULL, 0, 5, NULL); // 调用ReleaseSemaphore使当前资源计数器加1,当当前资源计数器<=5时,ReleaseSemaphore返回成功 // 当while循环结束时,当前资源计数=5,g_Data[0]/g_Data[1]/g_Data[2]/g_Data[3]/g_Data[4]赋值 while (TRUE) { b477 if (ReleaseSemaphore(h_Semaphore, 1, NULL)) { g_Data[i] = i + 10; i++; } else { cout << "ReleaseSemaphore error" << endl; break; } } for (int i = 0; i < 10; i++) { cout << g_Data[i] << endl; } // 在线程中调用信号量的等待函数WaitForSingleObject三次,则当前资源计数器减3 // 此时当前资源计数=2 handle = (HANDLE)_beginthreadex(NULL, 0, &ThreadFunc, NULL, 0, &unThreadID); WaitForSingleObject(handle, INFINITE); // 当前资源计数=2,则还可以调用ReleaseSemaphore3次 // g_Data[5]/g_Data[6]/g_Data[7]赋值 while (TRUE) { if (ReleaseSemaphore(h_Semaphore, 1, NULL)) { g_Data[i] = i + 10; i++; } else { cout << "ReleaseSemaphore error" << endl; break; } } for (int i = 0; i < 10; i++) { cout << g_Data[i] << endl; } getchar(); CloseHandle(h_Semaphore); return 0; }
最后输出结果为:
ReleaseSemaphore error
10
11
12
13
14
0
0
0
0
0
ReleaseSemaphore error
10
11
12
13
14
15
16
17
0
0
相关文章推荐
- 第9章 用内核对象进行线程同步(3)_信号量(semaphore)、互斥对象(mutex)
- Windows核心编程 用内核对象进行线程同步
- Windows核心编程(八)用内核对象进行线程同步
- Windows-核心编程-09-如何用内核对象进行线程同步-信号内核对象
- Chapter09-“内核模式下的线程同步”之信号量内核对象
- 第九章:用内核对象进行线程同步(二) .
- 线程同步--信号量内核对象
- Chapter09-“内核模式下的线程同步”之信号量内核对象
- 《Windows via C/C++》学习笔记 —— 内核对象的“线程同步”之“信号量”
- Windows核心编程:(六)用内核对象进行线程同步
- <<windows核心编程>>读书笔记---第9章 内核对象进行线程同步
- windows核心编程---用内核对象进行线程同步
- Windows核心编程笔记(九)使用内核对象进行线程同步
- Windows核心编程学习九:利用内核对象进行线程同步
- 第9章 用内核对象进行线程同步(2)_可等待计时器(WaitableTimer)
- 用内核对象进行线程同步——互斥量内核对象
- 进程与线程(五)用内核对象进行线程同步(上)
- 摘自windows核心编程之用内核对象进行线程同步
- windows核心编程-9.用内核对象进行线程同步