• 线程同步——内核对象实现线程同步——等待函数


      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 //定义线程函数2
    101 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 //创建线程1
    116 HANDLE hThreadOne = CreateThread(NULL,0,ThreadFunOne,0,0,NULL);
    117 CloseHandle(hThreadOne);
    118 
    119 //创建线程2
    120 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) ; //运行结果为2
    132 //WaitForMultipleObjects(2,h,TRUE,INFINITE) ; //运行结果为1
    133 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  
  • 相关阅读:
    objc之method&class attributes
    iOS之Export UIAutomation script
    js's forin vs oc's forin
    iOS新加速计事件
    Mac之Font管理
    iOS之VoiceOver
    OC之initialize
    C++常见问题
    objc新老runtime接口类型对比
    dlopen之mode参数详解
  • 原文地址:https://www.cnblogs.com/yfyzy/p/3916186.html
Copyright © 2020-2023  润新知