windows多线程(七) 事件event

前面说的互斥量Mutex与关键段CriticalSection都不能实现线程的同步,只能实现互斥,接下来我们用时间event就可以实现线程的同步了,事件也是一个内核对象。

一、相关函数说明

(一) 创建事件
1.函数原型

HANDLE WINAPI CreateEventW(
                _In_opt_ LPSECURITY_ATTRIBUTES lpEventAttributes,
                _In_ BOOL bManualReset,
                _In_ BOOL bInitialState,
                _In_opt_ LPCWSTR lpName
                );
2.参数说明
  • 第一个参数表示安全控制,一般直接传入NULL。

  • 第二个参数确定事件是手动置位还是自动置位,传入TRUE表示手动置位,传入FALSE表示自动置位。如果为自动置位,则对该事件调用WaitForSingleObject()后会自动调用ResetEvent()使事件变成未触发状态。

  • 第三个参数表示事件的初始状态,传入TRUR表示已触发。

  • 第四个参数表示事件的名称,传入NULL表示匿名事件。

(二) 打开事件
1.函数原型

HANDLE WINAPI OpenEventW(
                _In_ DWORD dwDesiredAccess,
                _In_ BOOL bInheritHandle,
                _In_ LPCWSTR lpName
                );
2.参数说明
  • 第一个参数表示访问权限,对事件一般传入EVENT_ALL_ACCESS。

  • 第二个参数表示事件句柄继承性,一般传入TRUE即可。

  • 第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个事件。

(三) 触发事件
1.函数原型

BOOL WINAPI SetEvent(
              _In_ HANDLE hEvent
            );
2.参数说明
  • 函数说明:每次触发后,必有一个或多个处于等待状态下的线程变成可调度状态。

  • hEvent 为要触发的事件的句柄(内核对象)

(四)、 将事件设为末触发
1.函数原型

BOOL WINAPI ResetEvent(
              _In_ HANDLE hEvent
            );
2.参数说明
  • hEvent 为要触发的事件的句柄(内核对象)

二、实例

前面我们用关键段和互斥量无法实现线程同步,在前面的程序中,我们可以实现对全局资源互斥访问,即每个线程给全局资源加一,现在使用事件可以时间线程同步,即实现每个线程按顺序依次给全局资源加一,代码如下:



//使用事件进行线程同步

#include<iostream>
#include <windows.h>

using namespace std;

CRITICAL_SECTION g_csVar;
HANDLE g_event;
const int THREAD_NUM = 10;
int g_Num = 0;

DWORD WINAPI  Func(LPVOID);


int main()
{
    g_event = CreateEvent(NULL, false, false, NULL);    //初始化事件为未触发状态
    InitializeCriticalSection(&g_csVar);
    DWORD  ThreadId[THREAD_NUM];
    HANDLE handle[THREAD_NUM];
    int i = 0;
    while (i < THREAD_NUM)
    {
        handle[i] = CreateThread(NULL, 0, Func, &i, 0, &ThreadId[i]);
        WaitForSingleObject(g_event, INFINITE); //等待事件被触发
        i++;
    }
    WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);

    CloseHandle(g_event);
    DeleteCriticalSection(&g_csVar);
    return 0;
}


DWORD WINAPI Func(LPVOID p)
{
    int nThreadNum = *(int*)p;
    
    EnterCriticalSection(&g_csVar);
    cout << "线程编号为:" << nThreadNum << " 给全局资源g_Num 加1,现在给全局资源g_Num值为:" << ++g_Num << endl;
    LeaveCriticalSection(&g_csVar);
    SetEvent(g_event);  //触发事件
    return 0;
}

运行结果如下所示:

猜你喜欢

转载自www.cnblogs.com/ay-a/p/9114006.html