部分转载自:http://blog.youkuaiyun.com/morewindows/article/details/7445233
步骤:
1、CreateEvent,创建一个事件内核对象。
2、SetEvent,将一个事件内核对象设为触发状态。而WaitForSingleObject函数就是等待一个事件被触发后,才继续执行。其实就相当于一个通电开关,按下了,才通电,通电了,才能继续执行。
3、ResetEvent,将一个事件内核对象设为未触发状态。
4、CloseHandle,关闭内核对象。
事件内核对象的个人理解:
1、事件对象可以分为2种,一种为自动重置事件,别一种为手动重置事件。
自动重置事件:当线程成功等待到自动重置对象的时候,对象就会自动重置为未触发状态,而且只允许一个线程得到自动重置对象。。一定记住是一等到,马上就重置了。
手动重置事件:必须手动将一个事件对象重置,或者线程结束时自动重置。但是手动重置事件允许多个线程得到事件。所以由于这种特性,所以拖动重置事件,一般只用来对只读的数据进行处理,否则可能出现不可预料的结果。
2、事件对象,就如《windows核心编程》中所说的,就是一面旗帜,当有这个信号时,就执行操作。
代码:
#include <stdio.h>
#include <process.h>
#include <windows.h>
long g_nNum;
unsigned int __stdcall Fun(void *pPM);
const int THREAD_NUM = 10;
//事件与关键段
HANDLE g_hThreadEvent;
CRITICAL_SECTION g_csThreadCode;
int main()
{
printf(" 经典线程同步 事件Event\n");
printf(" -- by MoreWindows( http://blog.youkuaiyun.com/MoreWindows ) --\n\n");
//初始化事件和关键段 自动置位,初始无触发的匿名事件
g_hThreadEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
InitializeCriticalSection(&g_csThreadCode);
HANDLE handle[THREAD_NUM];
g_nNum = 0;
int i = 0;
while (i < THREAD_NUM)
{
handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
WaitForSingleObject(g_hThreadEvent, INFINITE); //等待事件被触发
i++;
}
WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
//销毁事件和关键段
CloseHandle(g_hThreadEvent);
DeleteCriticalSection(&g_csThreadCode);
return 0;
}
unsigned int __stdcall Fun(void *pPM)
{
int nThreadNum = *(int *)pPM;
g_nNum++;
printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_nNum);
SetEvent(g_hThreadEvent); //触发事件
return 0;
}
结果:
思考:
线程同步,就是让线程以一种有序的方式来执行。