Chapter09-"内核模式下的线程同步"之事件内核对象
来源:互联网 发布:java服务器端开发框架 编辑:程序博客网 时间:2024/06/06 02:48
有两种事件内核对象:自动事件和手动事件。当手动事件被触发时,所以该事件的等待线程都编程可调度状态;而自动事件被触发时,只有个一个等待该事件线程变成可调度状态。
下面再逐个讲解Event的相关函数:
a) 创建事件函数——CreateEvent函数:
HANDLE CreateEvent(
PSECURITY_ATTRIBUTESpsa,
BOOLbManualReset,
BOOLbInitialState,
PCTSTRpszName);
具体的函数参数及用法,请查看上面的超链接。
b) 第二创建事件的函数——CreateEventEx函数:
HANDLE CreateEventEx(
PSECURITY_ATTRIBUTESpsa,
PCTSTRpszName,
DWORDdwFlags,
DWORDdwDesiredAccess);
c) 访问某个打开的事件(Event)——OpenEvent函数:
HANDLE OpenEvent(
DWORDdwDesiredAccess,
BOOLbInherit,
PCTSTRpszName)
在pszName传递创建事件时函数的pszName参数值。
d) 使得某个事件处于触发状态——SetEvent函数:
BOOL SetEvent(HANDLE hEvent);
e) 将某个事件设置为非触发状态——ResetEvent函数:
BOOL ResetEvent(HANDLE hEvent);
f) 特别的函数——PluseEvent函数:
BOOL PulseEvent(HANDLE hEvent);
其作用相当于在调用SetEvent函数后立即调用ResetEvent函数,功能就是一次启用一个线程。因为手动方式的事件时,当事件触发时,所有的该事件阻塞的线程都会转为可调度状态。如果你调用PluseEvent函数后,在系统调用某一个线程后,由于立马将事件设置为非触发状态,这是其他线程也就再次被阻塞了。解释起来好像比较麻烦,不过该函数在实际使用过程中也少有用到。
看一个创建事件时设置手动方式的事件(manual-reset events)示例:
// Create a global handle to a manual-reset, nonsignaled event.HANDLE g_hEvent;int WINAPI _tWinMain(...) {// Create the manual-reset, nonsignaled event.g_hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);// Spawn 3 new threads.HANDLE hThread[3];DWORD dwThreadID;hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID);hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID);hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID);OpenFileAndReadContentsIntoMemory(...);// Allow all 3 threads to access the memory.SetEvent(g_hEvent);...}DWORD WINAPI WordCount(PVOID pvParam) {// Wait until the file's data is in memory.WaitForSingleObject(g_hEvent, INFINITE);// Access the memory block....return(0);}DWORD WINAPI SpellCheck (PVOID pvParam) {// Wait until the file's data is in memory.WaitForSingleObject(g_hEvent, INFINITE);// Access the memory block....return(0);}DWORD WINAPI GrammarCheck (PVOID pvParam) {// Wait until the file's data is in memory.WaitForSingleObject(g_hEvent, INFINITE);// Access the memory block....return(0);}
创建事件时设置为自动方式时的事件(auto-reset event)示例:
// Create a global handle to a auto-reset, nonsignaled event.HANDLE g_hEvent;int WINAPI _tWinMain(...) {// Create the auto-reset, nonsignaled event.g_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);// Spawn 3 new threads.HANDLE hThread[3];DWORD dwThreadID;hThread[0] = _beginthreadex(NULL, 0, WordCount, NULL, 0, &dwThreadID);hThread[1] = _beginthreadex(NULL, 0, SpellCheck, NULL, 0, &dwThreadID);hThread[2] = _beginthreadex(NULL, 0, GrammarCheck, NULL, 0, &dwThreadID);OpenFileAndReadContentsIntoMemory(...);// Allow all 3 threads to access the memory.SetEvent(g_hEvent);...}DWORD WINAPI WordCount(PVOID pvParam) {// Wait until the file's data is in memory.WaitForSingleObject(g_hEvent, INFINITE);// Access the memory block....SetEvent(g_hEvent);return(0);}DWORD WINAPI SpellCheck (PVOID pvParam) {// Wait until the file's data is in memory.WaitForSingleObject(g_hEvent, INFINITE);// Access the memory block....SetEvent(g_hEvent);return(0);}DWORD WINAPI GrammarCheck (PVOID pvParam) {// Wait until the file's data is in memory.WaitForSingleObject(g_hEvent, INFINITE);// Access the memory block....SetEvent(g_hEvent);return(0);}
分析:对比上面的代码示例,细心的话你会发现:在自动方式下的代码中,每个线程在返回前都会调用SetEvent函数将事件设置为触发状态;而手动方式事件对应的函数中没有调用这个函数。
这是因为在自动方式下,事件每次转化为触发状态时只能使一个线程变成可调度状态,为了让其他线程也能被执行,所以在每个线程返回前再次将事件设置为触发状态,使得其他等待该事件的线程转为可调度状态从而被执行。
而手动方式下,则不同,当手动方式事件被SetEvent函数触发一次,它就一直保持触发态,直到再次调用ReSetEvent函数将它设为非触发态。
- Chapter09-"内核模式下的线程同步"之事件内核对象
- Chapter09-“内核模式下的线程同步”之可等待的计时器内核对象
- Chapter09-“内核模式下的线程同步”之信号量内核对象
- Chapter09-“内核模式下的线程同步”之互斥量内核对象
- Chapter09-"内核模式下的线程同步"之等待函数
- Windows Via C/C++:内核模式下的线程同步——事件内核对象
- 内核模式下的线程同步——事件内核对象
- -【内核对象线程同步】事件内核对象
- Windows内核模式的线程同步之事件(Event)
- 线程与事件内核对象的同步
- 线程同步--事件内核对象
- windows编程之内核模式下的线程同步
- Windows 内核模式下的线程同步
- 内核模式下线程同步
- 线程同步(2) - 内核模式下的线程同步
- 线程同步(2) - 内核模式下的线程同步
- 复习笔记之三--内核对象线程同步---事件
- 内核对象的线程同步
- ASP.NET页面回传后保持当前的滚动(垂直)位置
- Android开发--身高体重指数(BIM)计算--访问标识符号(android:id属性/XML说明文件与R.java资源文件/将字符串抽离XML/新增XML文件)
- 旋转数组中的最小元素。
- python实现Dijkstra法
- SPI message 基础 Part 2
- Chapter09-"内核模式下的线程同步"之事件内核对象
- 黑马程序员_.NET学习10(Eval()时间格式化)
- rpm安装方法
- android开发简单的计算器
- 从Java代码到Java堆理解和优化您的应用程序的内存使用
- rhel源文件安装yum
- 关于wlan的一些东西
- 在线工具:将图片透明化
- 查看文件的方法