<一>事件
事件主要用于线程间传递消息,通过事件来控制一个线程是处于执行状态还是处于挂起状态。
事件和互斥量之间的差别:
- 事件主要用于协调两个或者多个线程之间的动作,使其协调一致,符合逻辑。一个线程等待某个事件的发生,另一个线程则在事件发生后产生一个信号,通知那个正在等待的线程(我的理解:线程A等待键盘输入,线程B在有键盘输入后发送一个信号给A,使得A可以执行,事件就是“键盘输入”)。
- 互斥量主要是为了保证在任何时刻只有一个线程在使用共享资源,线程的运行次序是随机的,有操作系统决定,因此互斥量不能使两个线程按一定的顺序执行。
- 互斥量有信号状态是指线程正在拥有该互斥量,无信号是指没有线程拥有这个互斥量;对事件来说,当等待的事件发生时,事件对象处于活动状态,叫有信号状态,相反的,当等待的事件没有发生时,事件对象处于无信号状态。
- 事件一般分为两种:手动事件和自动事件。手动事件是指当事件对象处于活动状态时它会一直处于这个状态,直到显示地将其置为无信号状态;自动事件是指当事件处于有信号状态并有一个线程接收到该事件后,事件立即变为无信号状态。
<二>与事件有关的函数
函数名 | 作用 |
CreateEvent | 创建一个事件 |
OpenEvent | 打开一个已经创建的事件 |
SetEvent | 触发一个事件 |
ResetEvent | 复位一个事件 |
PulseEvent | 触发并重置一个事件 |
WaitForSingleObject | 等待单个事件 |
WaitForMultipleObject | 等待多个事件 |
#include <windows.h> #include <process.h> /* _beginthread, _endthread */ #include <iostream> #include <fstream> using namespace std; HANDLE hEvent; unsigned long _stdcall MyThread1(LPVOID lpParam) { cout<<"Wait for event "; WaitForSingleObject(hEvent,INFINITE); cout<<"Get the event "; return 1; } unsigned long _stdcall MyThread2(LPVOID lpParam) { Sleep(1000); cout<<"Signal the event "; SetEvent(hEvent); return 1; } int main() { HANDLE handle1,handle2; DWORD dw1,dw2; hEvent = CreateEvent(NULL,FALSE,FALSE,NULL); handle1 =CreateThread(NULL,NULL,MyThread1,NULL,NULL,&dw1); handle2 =CreateThread(NULL,NULL,MyThread2,NULL,NULL,&dw2); Sleep(6000); CloseHandle(handle1); CloseHandle(handle2); CloseHandle(hEvent); return 0; }
再看一个难一点的例子:两个读线程,一个写线程。
#include <windows.h> #include <process.h> /* _beginthread, _endthread */ #include <iostream> #include <fstream> using namespace std; HANDLE hWriteEvent; HANDLE hReadEvent[2]; int buff[5]; CRITICAL_SECTION cs; BOOL isRunning = true; unsigned long _stdcall WriteThread(LPVOID lpParam) { hWriteEvent = CreateEvent(NULL,TRUE,FALSE,NULL);//创建一个写事件,并处于有信号状态 int k = 1; while (isRunning) { if(WAIT_OBJECT_0==WaitForMultipleObjects(2,hReadEvent,true,0)) { for (int i = 0;i<5;i++) { buff[i]=(i+1)*k; } k++; PulseEvent(hWriteEvent); } } return 1; } unsigned long _stdcall ReadThread1(LPVOID lpParam) { hReadEvent[0] = CreateEvent(NULL,FALSE,TRUE,NULL); while (isRunning) { WaitForSingleObject(hWriteEvent,INFINITE); EnterCriticalSection(&cs); cout<<"Print from Thread #1:"; for (int i = 0;i<5;i++) cout<<buff[i]<<" "; cout<<endl; LeaveCriticalSection(&cs); SetEvent(hReadEvent[0]); } return 1; } unsigned long _stdcall ReadThread2(LPVOID lpParam) { hReadEvent[1] = CreateEvent(NULL,FALSE,TRUE,NULL); while (isRunning) { WaitForSingleObject(hWriteEvent,INFINITE); EnterCriticalSection(&cs); cout<<"Print from Thread #2:"; for (int i = 0;i<5;i++) cout<<buff[i]<<" "; cout<<endl; LeaveCriticalSection(&cs); SetEvent(hReadEvent[1]); } return 1; } unsigned long _stdcall ControlThread(LPVOID lpParam) { isRunning = FALSE; return 1; } int main() { HANDLE handle1,handle2,handle3,handle4; DWORD dw1,dw2,dw3,dw4; InitializeCriticalSection(&cs); handle1 = CreateThread(NULL,0,WriteThread,NULL,0,&dw1); handle2 = CreateThread(NULL,0,ReadThread1,NULL,0,&dw2); handle3 = CreateThread(NULL,0,ReadThread2,NULL,0,&dw3); Sleep(1000); handle4 = CreateThread(NULL,0,ControlThread,NULL,0,&dw4); CloseHandle(handle1); CloseHandle(handle2); CloseHandle(handle3); CloseHandle(handle4); CloseHandle(hWriteEvent); CloseHandle(hReadEvent[0]); CloseHandle(hReadEvent[1]); return 0; }