zoukankan      html  css  js  c++  java
  • 秒杀多线程第六篇 经典线程同步 事件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);

     

  • 相关阅读:
    工厂模式之简单工厂模式
    JavaMail(二):利用JavaMail发送复杂邮件
    JavaMail(一):利用JavaMail发送简单邮件
    浅谈Java中静态代码块和非静态代码块
    MySQL中常用转换函数介绍
    jquery easyui datagrid 分页 详解
    tomcat出现的PermGen Space问题(bat,或者eclipse启动。)
    把Blob 转化为字符串查询。
    日期相关---SimpleDateFormat的setLenient(true/false)-----自动计算日期
    处理同一个字段,多种日期格式
  • 原文地址:https://www.cnblogs.com/yuqilihualuo/p/3023993.html
Copyright © 2011-2022 走看看