秒杀多线程第六篇 经典线程同步 事件Event .
参考博客:http://blog.csdn.net/morewindows/article/details/7445233
使用Event来解决线程同步问题,Event其实是一个内核对象,下面列出相关的操作函数
1.创建事件
HANDLECreateEvent(
LPSECURITY_ATTRIBUTESlpEventAttributes,
BOOLbManualReset,
BOOLbInitialState,
LPCTSTRlpName
);
第一个参数:表示安全按控制一般传入NULL
第二个参数:确定事件是手动设置还是自动设置
手动设置(TRUE):触发后允许所有线程执行,一直到关闭为止
自动设置(FALSE):触发一次允许一个线程执行
如果为自动置位,则对该事件调用WaitForSingleObject()后
会自动调用ResetEvent()使事件变成未触发状态。
第三个参数:表示事件的初始状态,传入TRUE表示事件被触发
第四个参数:表示事件的名称,传入NULL表示匿名事件
2.根据名称获得事件的句柄
HANDLEOpenEvent(
DWORDdwDesiredAccess,
BOOLbInheritHandle,
LPCTSTRlpName //名称
);
第一个参数:表示访问权限,对事件一般传入EVENT_ALL_ACCESS
第二个参数表示事件句柄继承性,一般传入TRUE即可。
第三个参数表示名称,不同进程中的各线程可以通过名称来确保它们访问同一个事件。
3.触发事件(必须有一个或者多个线程等待调度)
BOOLSetEvent(HANDLEhEvent);
4.将事件设为未触发状态
BOOLResetEvent(HANDLEhEvent);
4.事件的清理与销毁
CloseHandle();
1 #include <stdio.h> 2 #include <process.h> 3 #include <windows.h> 4 5 //定义事件句柄 6 HANDLE g_hThreadEvent; 7 8 //关键段的定义 9 CRITICAL_SECTION g_csThreadCode; 10 long g_num; //登录次数 11 unsigned int __stdcall Fun(void *pPM); //线程函数 12 const DWORD THREAD_NUM = 10;//启动线程数 13 unsigned int __stdcall Fun(void *pPM) 14 { 15 //由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来 16 int nThreadNum = *(int *)pPM; //子线程获取参数 17 SetEvent(g_hThreadEvent);//3.事件被触发 18 Sleep(50);//some work should to do 19 EnterCriticalSection(&g_csThreadCode);//进入子线程序号的关键区域 20 g_num++; //处理全局资源 21 Sleep(0);//some work should to do 22 printf("线程编号为%d 全局资源值为%d\n", nThreadNum, g_num); 23 LeaveCriticalSection(&g_csThreadCode); 24 return 0; 25 } 26 int main() 27 { 28 printf(" CS的演示与Event\n"); 29 g_num = 0; 30 g_hThreadEvent=CreateEvent(NULL,FALSE,FALSE,NULL); //1.创建事件 31 32 //关键段的初始化 33 InitializeCriticalSection(&g_csThreadCode); 34 HANDLE handle[THREAD_NUM]; 35 int i=0; 36 while (i<THREAD_NUM) 37 { 38 handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL); 39 i++; 40 WaitForSingleObject(g_hThreadEvent,INFINITE);//2.等待事件被触发 41 } 42 43 WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE); 44 CloseHandle(g_hThreadEvent);//5.销毁事件 45 //离开关键区域 46 LeaveCriticalSection(&g_csThreadCode); 47 48 return 0; 49 }
运行结果:
结果发现线程号没有重复,且全局资源递增,说明主线程与子线程达到了同步,子线程之间形成了互斥
PulseEvent()来发出一个短暂的触发脉冲相当于同事调用
SetEvent(g_hThreadEvent);
ResetEvent(g_hThreadEvent);