VC 线程同步(事件)

1.创建事件

HANDLE CreateEvent( //创建事件
LPSECURITY_ATTRIBUTES lpEventAttributes,// 安全属性
BOOL bManualReset,// 复位方式
BOOL bInitialState,// 初始状态
LPCTSTR lpName // 对象名称
);
返回值:
    如果函数调用成功,函数返回事件对象的句柄。如果对于命名的对象,在函数调用前已经被创建,函数将返回存在的事件对象的句柄,而且在GetLastError函数中返回ERROR_ALREADY_EXISTS。
如果函数失败,函数返回值为NULL,如果需要获得详细的错误信息,需要调用GetLastError。

参数说明:
lpEventAttributes[输入]
    一个指向[SECURITY_ATTRIBUTES]结构的指针,确定返回的句柄是否可被子进程继承。如果lpEventAttributes是NULL,此句柄不能被继承。
    Windows NT/2000:lpEventAttributes的结构中的成员为新的事件指定了一个安全符。如果lpEventAttributes是NULL,事件将获得一个默认的安全符。
 
bManualReset[输入]         
      创建的Event是自动复位还是人工复位.如果true,人工复位,   一旦该Event被设置为有信号,则它一直会等到ResetEvent()API被调用时才会恢复为无信号.   
      如果为false,Event被设置为有信号,则当有一个wait到它的Thread时,  该Event就会自动复位,变成无信号.  
      如果想在每次调用WaitForSingleObject 后让WINDOWS为您自动地把事件地状态恢复为”无信号”状态,必须把该参数设为FALSE,否则,您必须每次调用ResetEvent函数来清除事件的信号。
bInitialState[输入]           
      初始状态,true,有信号,false无信号   
lpName[输入]               
    指定事件的对象的名称,是一个以0 结束的字符串[指针]。
    名称的[字符格式]限定在MAX_PATH之内。名字是对大小写敏感的。
    如果lpName指定的名字,与一个存在的命名的事件对象的名称相同,函数将请求EVENT_ALL_ACCESS来访问存在的对象。这时候,由于bManualReset和bInitialState参数已经在创建事件的进程中设置,这两个参数将被忽略。如果lpEventAttributes是参数不是NULL,它将确定此句柄是否可以被继承,但是其[安全描述符]成员将被忽略。
    如果lpName为NULL,将创建一个无名的事件对象。
    如果lpName的和一个存在的信号、互斥、等待计时器、作业或者是文件映射对象名称相同,函数将会失败,在GetLastError函数中将返回ERROR_INVALID_HANDLE。造成这种现象的原因是这些对象共享同一个命名空间。

2.打开事件

HANDLE WINAPI OpenEvent(
  _In_ DWORD dwDesiredAccess,
  _In_ BOOL bInheritHandle,
  _In_ LPCTSTR lpName
);
参数:
dwDesiredAccess [in]
  对事件对象的访问。如果指定对象的安全描述符不允许请求访问调用进程,则该函数将失败。
  有关访问权限的列表,请参阅 [同步对象安全和访问权限](https://msdn.microsoft.com/en-us/library/windows/desktop/ms686670(v=vs.85).aspx)。

bInheritHandle [in]
如果此值为TRUE,则由此进程创建的进程将继承该句柄。否则,进程不会继承此句柄。

lpName [in]
参考上面的lpName
## 返回值
如果函数成功,则返回值是事件对象的句柄。
如果函数失败,返回值为NULL。要获得更多的错误信息,请调用 [GetLastError](https://msdn.microsoft.com/en-us/library/windows/desktop/ms679360(v=vs.85).aspx)。

3.重置和触发事件

BOOL ResetEvent(HANDLE hEvent);  //事件对象设置为无信号状态。
BOOL SetEvent(HANDLE hEvent);  //事件对象设置为有信号状态。 
BOOL PulseEvent(HANDLE hEvent);  //事件对象设置为有信号状态,脉冲一个事件
这里的hEvent就是上面创建成功的返回值,这里不多介绍了,主要说说SetEvent和PulseEvent区别
PulseEvent与SetEvent在事件对象为自动模式时是没分别的。 
在人工模式下,区别应该是: 
事件对象调用SetEvent()后,所有等待线程释放,事件对象如没有调用ResetEvent(),将一直处于有信号状态,下一个时间片出现的等待线程直接导致被释放; 
事件对象调用PulseEvent()后,所有等待线程释放,事件对象重置为无信号状态,下一个时间片出现的等待线程将等待事件对象设置为有信号状态才释放。

4.等待内核对象函数

DWORD WINAPI WaitForSingleObject(
  _In_ HANDLE hHandle,
  _In_ DWORD  dwMilliseconds
);
WaitForSingleObject 函数用来检测 hHandle 事件的信号状态,当函数的执行时间超过 dwMilliseconds 就返回,
但如果参数 dwMilliseconds 为 INFINITE 时函数将直到相应时间事件变成有信号状态才返回,否则就一直等待下去,直到 WaitForSingleObject 有返回直才执行后面的代码。
参数 :
hHandle 
是一个事件的句柄,
dwMilliseconds 
是时间间隔。
如果时间是有信号状态返回 WAIT_OBJECT_0 ,如果时间超过 dwMilliseconds 值但时间事件还是无信号状态则返回 WAIT_TIMEOUT 。
hHandle 可以是下列对象的句柄:
Change notification 
Console input 
Event 
Job 
Memory resource notification 
Mutex 
Process 
Semaphore 
Thread 
Waitable timer  
返回值:
如果此函数成功,该函数的返回之标识了引起该函数返回的事件。返回值如下:
  WAIT_ABANDONED(0x00000080L)
  指定的对象是一个互斥对象,该对象没有被拥有该对象的线程在线程结束前释放。互斥对象的所有权被同意授予调用该函数的线程。互斥对象被设置成为无信号状态。
  WAIT_OBJECT_0 (0x00000000L)
  指定的对象出有有信号状态。
  WAIT_TIMEOUT (0x00000102L)
  超过等待时间,指定的对象处于无信号状态
如果失败,返回 WAIT_FAILED;

5.下面一个例子来展示下怎么用事件来实现线程同步

#include <stdio.h>
#include <Windows.h>
#include <thread>
HANDLE g_hEvent;

UINT thread1()
{
    printf("进入线程了,等待5秒\n");
    WaitForSingleObject(g_hEvent, INFINITE);
    printf("等待结束了,向下执行了!\n");
    return 0;
}

UINT thread2()
{
    Sleep(5000);
    SetEvent(g_hEvent);
    return 0;
}

int main(int argc, char*argv[])
{
    g_hEvent = CreateEvent(NULL, true, FALSE, NULL);
    ResetEvent(g_hEvent);

    std::thread t1(thread1 );//开启线程1
    std::thread t2(thread2 );//开启线程2
    t1.join();
    system("pause");
    return 0;
}

通过以上学习可以发现,代码中的一个参数可能对应着很多的知识,这里一个例子并不能完全的把所有的参数演示完毕,在以后的项目中大家可以更多的去体会到其他的参数的作用的。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,711评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,079评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,194评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,089评论 1 286
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,197评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,306评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,338评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,119评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,541评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,846评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,014评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,694评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,322评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,026评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,257评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,863评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,895评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,914评论 25 707
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,221评论 11 349
  • 13岁的时候,我意识到自己长了一对虎牙,这让我不同于其他同学,甚至被说像吸血鬼。借一次蛀牙补洞的机会,我认识到...
    落雨哒哒阅读 314评论 0 2
  • 字数(1214),建议阅读(2-3分钟) 从信息传播角度思考,互联网即通过运用合理的信号传播途径(有线、无线、...
    沃菲斯熊猫阅读 498评论 3 2
  • 北京,体感温度零下6度,用滴滴约了一辆快车。跟朋友一路聊天,浑然不觉口袋里的东西正一点点的掉在车座上。 我在电话中...
    茶珂可阅读 166评论 0 0