• 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;
    }
  • 相关阅读:
    鼠标跟随效果 vue或者js通用
    element 多个文件上传多次http请求解决方法
    快速判断数组中值是否重复
    vue-resource+element upload上传(遇到formData总是变为object格式)
    element UI 下拉菜单滚动监听(vue指令)
    echarts环形图自动定位radius
    echarts地图散点高亮弹框制作
    js实现table表格相同内容按需合并
    element ui表格相同内容自动合并
    hadoop yarn
  • 原文地址:https://www.cnblogs.com/LCCRNblog/p/3386097.html
Copyright © 2020-2023  润新知