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;
}

运行结果如下所示:

posted @ 2018-05-30 22:59  ay-a  阅读(5603)  评论(0编辑  收藏  举报