首页 > 代码库 > 线程同步——内核对象实现线程同步——等待函数
线程同步——内核对象实现线程同步——等待函数
1 对于内核对象实现线程同步,不得不提三点: 2 1)大多数内核对象既有触发也有未触发两个状态 3 比如:进程、线程、作业、文件流、事件、可等待的计时器、信号量、互斥量 4 2)等待函数:等待函数使线程自愿进入等待状态,直到指定的内核对象变为触发状态为止, 5 说道等待我们最喜欢不过了,因为这样不会浪费我们宝贵的CPU时间。 6 3)对于自动重置对象来说,当对象被触发时,函数会自动检测到(手动重置对象为触发是,函数也能检测到), 7 并开始执行,但是在函数会在返回之前使事件变为非触发状态。 8 9 下面介绍一下最常见的几个等待函数: 10 1): 11 DWORD WaitForSingleObject( HANDLE hHandle, DWORD dwMilliseconds ); 12 第一个参数hHandle用来标识要等待的内核对象,第二个人参数dwMilliseconds用来标识自愿花多长时间等待。 13 14 下面的函数是告诉系统,线程希望一直等待,直到线程所在的进程终止或hProcess标识的对象变为触发状态 15 WaitForSingleObject(hProcess,INFINITE); 16 17 关于等待函数的返回问题,我们看下面代码: 18 DWORD dw = WaitForSingleObject(hProcess,5000) ; 19 20 switch(dw) 21 { 22 case WAIT_OBJECT_0: 23 // 线程等待对象被触发,也就是说线程还没到5000的等待时间就开始工作啦 24 break; 25 26 case WAIT_TIMEOUT: 27 //线程等待超时,线程在5000的时间还是没有等到对象被触发,但是时间到了,线程也要开始工作啦 28 break; 29 30 case WAIT_FAILED: 31 //线程传人了一个无效的句柄,这时后果可能就无法预料了 32 break; 33 } 34 35 2) 36 DWORD WaitForMultipleObjects( 37 DWORD nCount, 38 CONST * HANDLE phObjects, 39 BOOL bWaitAll , 40 DWORD dwMilliseconds) ; 41 第一个参数nCount表示我们希望检测内核对象的数量,这个值必须在 1到 MAXIMUM_WAIT_OBJECTS 最大是64, 42 我相信已经够多了,真的需要那么多时就不应该用这种方法了哦 43 第二个参数phObjects,是一个指针,指向内核对象句柄的数组 44 第三个参数bWaitAll是告诉函数,我们希望用哪种方式。如果这个函数传入 TRUE , 45 那么在所有的内核对象被触发之前,函数不会允许调用线程执行。 46 第四个参数dwMilliseconds就是和WaitForSingleObject的第二个参数一样了,我们最多等待多久, 47 当然也可以传入INFINITE表示在满足条件前愿意一直等待。 48 49 关于WaitForMultipleObjects的返回值,我们也一起来看看代码哇: 50 51 HANDLE h[3]; 52 h[0] = hProgress1 ; 53 h[1] = hProgress2 ; 54 h[2] = hProgress3 ; 55 56 DWORD dw = WaitForMultipleObjects(3,h,FALSE,5000) ; 57 switch(dw) 58 { 59 case WAIT_FAILED: 60 //传入无效句柄,后果就不多说了哈 61 break; 62 63 case WAIT_TIMEOUT: 64 //线程等待超时,线程在5000的时间还是没有等到对象被触发,但是时间到了,线程要开始工作啦 65 break; 66 67 case WAIT_OBJECT_0 + 0: 68 //对象h[0]为触发状态 69 break; 70 71 case WAIT_OBJECT_0 + 1: 72 //对象h[1]为触发状态 73 break; 74 75 case WAIT_OBJECT_0 + 2: 76 //对象h[2]为触发状态 77 break; 78 } 79 //这样写也有弊端,比如h[0] 和 h[1]同时为触发时,结果h[0]处理完就返回了 80 把下面代码DWORD WINAPI ThreadFunOne(PVOID pvParam) 线程中注释行运行,便可以体会体会了。 81 82 #include "windows.h" 83 #include "iostream" 84 using namespace std; 85 long g_x = 0 ; 86 87 // 定义一个事件对象1 88 // HANDLE g_hEvent1 ; 89 // 90 // 定义一个事件对象2 91 // HANDLE g_hEvent2; 92 93 HANDLE h[2]; 94 95 96 97 //定义线程函数1 98 DWORD WINAPI ThreadFunOne(PVOID pvParam) ; 99 100 //定义线程函数2101 DWORD WINAPI ThreadFunTwo(PVOID pvParam);102 103 int main()104 {105 106 //创建一个手动重置的事件对象107 h[0] = CreateEvent(NULL,FALSE,TRUE,NULL);108 109 //创建一个手动重置的事件对象110 h[1] = CreateEvent(NULL,FALSE,TRUE,NULL);111 112 //把事件设为未触发状态113 // ResetEvent(g_hEvent);114 115 //创建线程1116 HANDLE hThreadOne = CreateThread(NULL,0,ThreadFunOne,0,0,NULL);117 CloseHandle(hThreadOne);118 119 //创建线程2120 HANDLE hThreadTwo = CreateThread(NULL,0,ThreadFunTwo,0,0,NULL);121 CloseHandle(hThreadTwo);122 123 //让主线程先挂起,确保其它线程执行完成124 Sleep(1000); 125 cout<<g_x<<endl;126 return 0 ;127 }128 129 DWORD WINAPI ThreadFunOne(PVOID pvParam) 130 {131 WaitForMultipleObjects(2,h,FALSE,INFINITE) ; //运行结果为2132 //WaitForMultipleObjects(2,h,TRUE,INFINITE) ; //运行结果为1133 g_x++;134 135 return 0;136 }137 138 DWORD WINAPI ThreadFunTwo(PVOID pvParam)139 {140 Sleep(200);141 WaitForSingleObject(h[1],INFINITE);142 g_x++; 143 144 return 0;145 }146
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。