Windows环境下多线程编程原理与应用读书笔记(7)————事件及其应用

<一>事件

       事件主要用于线程间传递消息,通过事件来控制一个线程是处于执行状态还是处于挂起状态。

       事件和互斥量之间的差别:

  1. 事件主要用于协调两个或者多个线程之间的动作,使其协调一致,符合逻辑。一个线程等待某个事件的发生,另一个线程则在事件发生后产生一个信号,通知那个正在等待的线程(我的理解:线程A等待键盘输入,线程B在有键盘输入后发送一个信号给A,使得A可以执行,事件就是“键盘输入”)。
  2. 互斥量主要是为了保证在任何时刻只有一个线程在使用共享资源,线程的运行次序是随机的,有操作系统决定,因此互斥量不能使两个线程按一定的顺序执行。
  3. 互斥量有信号状态是指线程正在拥有该互斥量,无信号是指没有线程拥有这个互斥量;对事件来说,当等待的事件发生时,事件对象处于活动状态,叫有信号状态,相反的,当等待的事件没有发生时,事件对象处于无信号状态。
  4. 事件一般分为两种:手动事件和自动事件。手动事件是指当事件对象处于活动状态时它会一直处于这个状态,直到显示地将其置为无信号状态;自动事件是指当事件处于有信号状态并有一个线程接收到该事件后,事件立即变为无信号状态。

<二>与事件有关的函数

函数名 作用
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;
}
原文地址:https://www.cnblogs.com/LCCRNblog/p/3386097.html