您的位置:首页 > 其它

秒杀多线程第六篇 经典线程同步 事件Event .

2013-04-16 13:58 246 查看
参考博客:/article/1358219.html

使用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();

#include <stdio.h>
#include <process.h>
#include <windows.h>

//定义事件句柄
HANDLE  g_hThreadEvent;

//关键段的定义
CRITICAL_SECTION  g_csThreadCode;
long g_num; //登录次数
unsigned int __stdcall Fun(void *pPM); //线程函数
const DWORD THREAD_NUM = 10;//启动线程数
unsigned int __stdcall Fun(void *pPM)
{
//由于创建线程是要一定的开销的,所以新线程并不能第一时间执行到这来
int nThreadNum = *(int *)pPM; //子线程获取参数
SetEvent(g_hThreadEvent);//3.事件被触发
Sleep(50);//some work should to do
EnterCriticalSection(&g_csThreadCode);//进入子线程序号的关键区域
g_num++;  //处理全局资源
Sleep(0);//some work should to do
printf("线程编号为%d  全局资源值为%d\n", nThreadNum, g_num);
LeaveCriticalSection(&g_csThreadCode);
return 0;
}
int main()
{
printf("     CS的演示与Event\n");
g_num = 0;
g_hThreadEvent=CreateEvent(NULL,FALSE,FALSE,NULL);  //1.创建事件

//关键段的初始化
InitializeCriticalSection(&g_csThreadCode);
HANDLE  handle[THREAD_NUM];
int i=0;
while (i<THREAD_NUM)
{
handle[i] = (HANDLE)_beginthreadex(NULL, 0, Fun, &i, 0, NULL);
i++;
WaitForSingleObject(g_hThreadEvent,INFINITE);//2.等待事件被触发
}

WaitForMultipleObjects(THREAD_NUM, handle, TRUE, INFINITE);
CloseHandle(g_hThreadEvent);//5.销毁事件
//离开关键区域
LeaveCriticalSection(&g_csThreadCode);

return 0;
}


运行结果:



结果发现线程号没有重复,且全局资源递增,说明主线程与子线程达到了同步,子线程之间形成了互斥

PulseEvent()来发出一个短暂的触发脉冲相当于同事调用

SetEvent(g_hThreadEvent);

ResetEvent(g_hThreadEvent);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: