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

  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  

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

时间: 2024-12-25 19:56:29

线程同步——内核对象实现线程同步——等待函数的相关文章

线程同步——内核对象实现线程同步——可等待计时器内核对象

1 可等待计时器 2 可等待计时器是这样一种内核对象,他们会在某个指定的时间触发或每隔一段时间触发一次. 5 下面我们来介绍一下创建可等待计时器函数: 6 7 HANDLE CreateWaitableTimer( 8 LPSECURITY_ATTRIBUTES lpTimerAttributes, 9 BOOL bManualReset, 10 LPCSTR lpTimerName ); 11 第一.三个参数我想我也不用介绍了哈,这是创建内核对象基本都会有的参数. 12 第二个参数bManua

线程同步——内核对象实现线程同步——事件内核对象

1 事件内核对象 2 3 事件类型对象有两种不同类型,手动重置和自动重置 4 手动重置:当一个手动重置对象被触发时候,等待该对象的所有线程变为可调度. 5 自动重置:当一个自动重置对象被触发时,只有一个等待该事件的线程会变为可调度 6 7 下面是一个创建事件内核对象的函数: 8 HANDLE CreateEvent( 9 LPSECURITY_ATTRIBUTES lpEventAttributes, 10 BOOL bManualReset, 11 BOOL bInitialState, 12

线程同步——内核对象实现线程同步——信号量

1 /* 2 3 信号量内核对象 4 信号量与其它内核量相同,包含一个使用计数,除此之外还包含两个量. 5 一个最大资源计数和一个当前资源计数. 6 信号量规则如下: 7 如果当前资源计数大于0,那么信号量处于触发状态. 8 如果当前资源计数等于0,那么信号量处于未触发状态. 9 系统绝不会让当前资源计数变为负数. 10 当前资源计数绝不会大于最大资源计数. 11 12 下面我们看一下信号量的创建函数 13 HANDLE CreateSemaphore( 14 LPSECURITY_ATTRIB

线程与内核对象的同步

线程与内核对象的同步内核对象可以处于已通知或未通知状体进程,线程,作业,文件,控制台输入,文件修改,事件,可等待定时器 等待函数DWORD WaitForSingleObject(HANDLE hobject, DWORD dwMilliseconds); 同时查看若干个内核对象已通知状体DWORD WaitForMultipleObjects(DWORD dwCount,CONST HANDLE* phObjects,BOOL fWaitAll,DWORD dwMilliseconds);dw

Win32线程同步内核对象的比较

X86处理器上用户层到内核层的转换要花费600个CPU指令周期 临界区(关键代码段)不是内核对象 但当访问被占用的资源时会使用内核资源 功能同互斥但不可跨进程 (以上引用自:http://www.dewen.org/q/9561) WIN32内核对象都是由HANDLE操控 信号量(Semaphore) wait函数族使访问计数递减 当且仅当访问计数0时无信号 ReleaseSemaphore递增访问计数 互斥(Mutex) 有且仅有1个访问计数的信号量(二元信号量binary semaphore

线程与内核对象的同步-2

等待定时器内核事件CreateWaitableTimer(PSECURITY_ATTRIBUTES psa,BOOL fManualReset,PCTSTR pszName);进程可以获得它自己的与进程相关的现有等待定时器的句柄.HANDLE OpenWaitableTimer(DWORD dwDesiredAccess,BOOL bInheritHandle,PCTSTR pszName); 等待定时器对象总是在未通知状态中创建,必须调用SetWaitableTimer函数来告诉定时器你想在何

内核对象进行线程同步

前言: 具体的可等待的内核对象有: 进程,线程,作业,文件以及控制台的标准输入流/输出流/错误流,事件,可等待的计时器,信号量,互斥量. 等待函数: DWORD WaitForSingleObject( HANDLE hObject,//用来标识要等待的内核对象 DWORD dwMilliseconds);//等待的时间 DWORD WaitForMultipleObjects( DWORD dwCount,//函数检查的内核对象的数量(最大为MAXIMUM_WAIT_OBJECTS) CONS

第9章 用内核对象进行线程同步(2)_可等待计时器(WaitableTimer)

9.4 可等待的计时器内核对象——某个指定的时间或每隔一段时间触发一次 (1)创建可等待计时器:CreateWaitableTimer(使用时应把常量_WIN32_WINNT定义为0x0400) 参数 描述 psa 安全属性(如使用计数.句柄继承等) bManualReset 手动重置计时器还是自动重置计时器. ①当手动计时器被触发,所有正在等待计时器的线程都变可为可调度. ②当自动计时器被触发时,只有一个正在等待计数器的线程变为可调度 pszName 对象的名字 (2)也可以打开一个己经存在的

Windows API学习---线程与内核对象的同步

前言 若干种内核对象,包括进程,线程和作业.可以将所有这些内核对象用于同步目的.对于线程同步来说,这些内核对象中的每种对象都可以说是处于已通知或未通知的状态之中.这种状态的切换是由Microsoft为每个对象建立的一套规则来决定的.例如,进程内核对象总是在未通知状态中创建的.当进程终止运行时,操作系统自动使该进程的内核对象处于已通知状态.一旦进程内核对象得到通知,它将永远保持这种状态,它的状态永远不会改为未通知状态. 当进程正在运行的时候,进程内核对象处于未通知状态,当进程终止运行的时候,它就变