线程同步——内核对象实现线程同步——等待函数
2014-08-16 11:03
204 查看
对于内核对象实现线程同步,不得不提三点: 1)大多数内核对象既有触发也有未触发两个状态 比如:进程、线程、作业、文件流、事件、可等待的计时器、信号量、互斥量 2)等待函数:等待函数使线程自愿进入等待状态,直到指定的内核对象变为触发状态为止, 说道等待我们最喜欢不过了,因为这样不会浪费我们宝贵的CPU时间。 3)对于自动重置对象来说,当对象被触发时,函数会自动检测到(手动重置对象为触发是,函数也能检测到), 并开始执行,但是在函数会在返回之前使事件变为非触发状态。 下面介绍一下最常见的几个等待函数: 1): DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); 第一个参数hHandle用来标识要等待的内核对象,第二个人参数dwMilliseconds用来标识自愿花多长时间等待。 下面的函数是告诉系统,线程希望一直等待,直到线程所在的进程终止或hProcess标识的对象变为触发状态 WaitForSingleObject(hProcess,INFINITE); 关于等待函数的返回问题,我们看下面代码: DWORD dw = WaitForSingleObject(hProcess,5000) ; switch(dw) { case WAIT_OBJECT_0: // 线程等待对象被触发,也就是说线程还没到5000的等待时间就开始工作啦 break; case WAIT_TIMEOUT: //线程等待超时,线程在5000的时间还是没有等到对象被触发,但是时间到了,线程也要开始工作啦 break; case WAIT_FAILED: //线程传人了一个无效的句柄,这时后果可能就无法预料了 break; } 2) DWORD WaitForMultipleObjects( DWORD nCount, CONST * HANDLE phObjects, BOOL bWaitAll , DWORD dwMilliseconds) ; 第一个参数nCount表示我们希望检测内核对象的数量,这个值必须在 1到 MAXIMUM_WAIT_OBJECTS 最大是64, 我相信已经够多了,真的需要那么多时就不应该用这种方法了哦 第二个参数phObjects,是一个指针,指向内核对象句柄的数组 第三个参数bWaitAll是告诉函数,我们希望用哪种方式。如果这个函数传入 TRUE , 那么在所有的内核对象被触发之前,函数不会允许调用线程执行。 第四个参数dwMilliseconds就是和WaitForSingleObject的第二个参数一样了,我们最多等待多久, 当然也可以传入INFINITE表示在满足条件前愿意一直等待。 关于WaitForMultipleObjects的返回值,我们也一起来看看代码哇: HANDLE h[3]; h[0] = hProgress1 ; h[1] = hProgress2 ; h[2] = hProgress3 ; DWORD dw = WaitForMultipleObjects(3,h,FALSE,5000) ; switch(dw) { case WAIT_FAILED: //传入无效句柄,后果就不多说了哈 break; case WAIT_TIMEOUT: //线程等待超时,线程在5000的时间还是没有等到对象被触发,但是时间到了,线程要开始工作啦 break; case WAIT_OBJECT_0 + 0: //对象h[0]为触发状态 break; case WAIT_OBJECT_0 + 1: //对象h[1]为触发状态 break; case WAIT_OBJECT_0 + 2: //对象h[2]为触发状态 break; } //这样写也有弊端,比如h[0] 和 h[1]同时为触发时,结果h[0]处理完就返回了 把下面代码DWORD WINAPI ThreadFunOne(PVOID pvParam) 线程中注释行运行,便可以体会体会了。 #include "windows.h" #include "iostream" using namespace std; long g_x = 0 ; // 定义一个事件对象1 // HANDLE g_hEvent1 ; // // 定义一个事件对象2 // HANDLE g_hEvent2; HANDLE h[2]; //定义线程函数1 DWORD WINAPI ThreadFunOne(PVOID pvParam) ; //定义线程函数2 DWORD WINAPI ThreadFunTwo(PVOID pvParam); int main() { //创建一个手动重置的事件对象 h[0] = CreateEvent(NULL,FALSE,TRUE,NULL); //创建一个手动重置的事件对象 h[1] = CreateEvent(NULL,FALSE,TRUE,NULL); //把事件设为未触发状态 // ResetEvent(g_hEvent); //创建线程1 HANDLE hThreadOne = CreateThread(NULL,0,ThreadFunOne,0,0,NULL); CloseHandle(hThreadOne); //创建线程2 HANDLE hThreadTwo = CreateThread(NULL,0,ThreadFunTwo,0,0,NULL); CloseHandle(hThreadTwo); //让主线程先挂起,确保其它线程执行完成 Sleep(1000); cout<<g_x<<endl; return 0 ; } DWORD WINAPI ThreadFunOne(PVOID pvParam) { WaitForMultipleObjects(2,h,FALSE,INFINITE) ; //运行结果为2 //WaitForMultipleObjects(2,h,TRUE,INFINITE) ; //运行结果为1 g_x++; return 0; } DWORD WINAPI ThreadFunTwo(PVOID pvParam) { Sleep(200); WaitForSingleObject(h[1],INFINITE); g_x++; return 0; }
相关文章推荐
- 线程同步——内核对象实现线程同步——事件内核对象
- 《Windows via C/C++》学习笔记 —— 内核对象的“线程同步”之“等待函数”
- 线程同步——内核对象实现线程同步——可等待计时器内核对象
- -【内核对象线程同步】等待函数
- windows笔记-【内核对象线程同步】等待函数
- 线程同步——内核对象实现线程同步——信号量
- 线程同步-用内核对象进程线程同步
- 利用互斥对象实现线程同步
- 利用事件对象实现线程同步
- 《Windows via C/C++》学习笔记 —— 内核对象的“线程同步”之“等待定时器”
- windows笔记-【内核对象线程同步】互斥对象内核对象
- 《Windows via C/C++》学习笔记 —— 内核对象的“线程同步”之“事件内核对象”
- windows笔记-【内核对象线程同步】概述
- windows笔记-【内核对象线程同步】等待定时器内核对象
- windows笔记-【内核对象线程同步】互斥对象内核对象
- windows笔记-【内核对象线程同步】线程同步对象速查表
- windows笔记-【内核对象线程同步】成功等待的副作用
- static成员与Asp.net中Application对象的线程同步实现
- 线程同步的内核对象的使用
- windows笔记-【内核对象线程同步】等待定时器内核对象