这是整理孙鑫VC得到的关于线程同步方面的笔记.

n       事件对象也属于内核对象,包含一个使用计数,一个用于指明该事件是一个自动重置的事件还是一个人工重置的事件的布尔值,另一个用于指明该事件处于已通知状态还是未通知状态的布尔值。

n       有两种不同类型的事件对象。一种是人工重置的事件,另一种是自动重置的事件。当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程。得到事件对象后,因为是自动重置的事件对象,所以操作系统将该事件对象设置为非信号状态

//---------------------------------------------------以下手动重置事件对象不具有实际参考价值----------------------------------------------------------

#include <windows.h>

#include <iostream.h>

DWORD WINAPI Fun1Proc(

LPVOID lpParameter   // thread data

);

DWORD WINAPI Fun2Proc(

LPVOID lpParameter   // thread data

);

int tickets=100;

HANDLE g_hEvent;  //全局的句柄变量,用来保存所创建的事件对象的句柄。由于多个线程要访问g_hEvent这个对象,所以将其设置为全局变量。

void main()

{

HANDLE hThread1;

HANDLE hThread2;

hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);

hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);

CloseHandle(hThread1);

CloseHandle(hThread2);

g_hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);   //第三个状态为FALSE说明创建时事件初始化为无信号状态

/*(1)第二个参数设定TRUE为人工重置事件对象,当人工重置的事件得到通知时,等待该事件的所有线程均变为可调度线程。也就是说他们都可以同时运行。两个线程可以同时运行说明同步失败。ResetEvent(g_hEvent)手动把事件对象设置成非信号状态,人工重置必须显式的SetEvent设置有信号状态.(2)第二个参数设定FALSE为自动重置事件对象,当一个自动重置的事件得到通知时,等待该事件的线程中只有一个线程变为可调度线程,同时将该事件对象设置为非信号状态。尽量不要用人工重置事件对象,因为会出现下面的问题

*/

SetEvent(g_hEvent);//把事件对象设置成有信号状态,但这时候所有的线程都变成有信号状态,所以每个线程前面需要用ResetEvent

Sleep(4000);

CloseHandle(g_hEvent);

}

DWORD WINAPI Fun1Proc(

LPVOID lpParameter   // thread data

)

{

while(TRUE)

{

WaitForSingleObject(g_hEvent,INFINITE);

// ResetEvent(g_hEvent);  // 人工重置的事件对象,除非显示的调用ResetEvent(g_hEvent);  将事件对象设置为无信号状态,它将始终处于有信号状态

/*

在这用ResetEvent把护持对象设置成非信号状态是不可以的,因为它存在两个问题:

1)在单CPU的平台下,同一时刻只有一个线程能够运行。假设线程1先运行WaitForSingleObject(g_hEvent,INFINITE);它通过WaitForSingleObject(g_hEvent,INFINITE);得到了事件对象g_hEvent。但这个时候它的时间片终止了,轮到第二个线程运行。因为线程1的ResetEvent没有被执行,所有我们的事件对象仍然处于有信号状态。既然它是有信号状态,线程2就能得到我们这个事件。也就是我们这两个线程都进入了要保护的代码,当然结果是不可预料的。

2)在多CPU的平台下线程1和线程2可以同时运行。当它们请求到了事件对象后,你再将它们设为非信号状态已经不起作用了,因为它们已经进入到我们要保护的代码了。两个线程同时访问同一种资源当然结果是未知的。

*/

if(tickets>0)

{

Sleep(1);

cout<<"thread1 sell ticket : "<<tickets--<<endl;

}

else

break;

SetEvent(g_hEvent);  //将事件对象设置为有信号状态

}

return 0;

}

DWORD WINAPI Fun2Proc(

LPVOID lpParameter   // thread data

)

{

while(TRUE)

{

WaitForSingleObject(g_hEvent,INFINITE);

//            ResetEvent(g_hEvent);

/*

在这用ResetEvent把护持对象设置成非信号状态是不可以的,因为它存在两个问题:

1)在单CPU的平台下,同一时刻只有一个线程能够运行。假设线程1先运行WaitForSingleObject(g_hEvent,INFINITE);它通过WaitForSingleObject(g_hEvent,INFINITE);得到了事件对象g_hEvent。但这个时候它的时间片终止了,轮到第二个线程运行。因为线程1的ResetEvent没有被执行,所有我们的事件对象仍然处于有信号状态。既然它是有信号状态,线程2就能得到我们这个事件。也就是我们这两个线程都进入了要保护的代码,当然结果是不可预料的。

2)在多CPU的平台下线程1和线程2可以同时运行。当它们请求到了事件对象后,你再将它们设为非信号状态已经不起作用了,因为它们已经进入到我们要保护的代码了。两个线程同时访问同一种资源当然结果是未知的。

*/

if(tickets>0)

{

Sleep(1);

cout<<"thread2 sell ticket : "<<tickets--<<endl;

}

else

break;

SetEvent(g_hEvent);

}

return 0;

}

//---------------------------------------------------------------------------飘逸的分割线--------------------------------------------------------------------------

自动重置事件对象例子-----具有实用参考性

/*

自动重置事件对象,当事件对象为有信号状态的时候,等待该对象的线程只有一个能得到该事件对象,这时候系统会把他变成非信号状态,所以在这个线程运行结束之后,一定要用SetEvent把该事件对象重新设置成有信号状态

*/

#include <windows.h>

#include <iostream.h>

DWORD WINAPI Fun1Proc(

LPVOID lpParameter   // thread data

);

DWORD WINAPI Fun2Proc(

LPVOID lpParameter   // thread data

);

int tickets=100;

HANDLE g_hEvent;

void main()

{

HANDLE hThread1;

HANDLE hThread2;

hThread1=CreateThread(NULL,0,Fun1Proc,NULL,0,NULL);

hThread2=CreateThread(NULL,0,Fun2Proc,NULL,0,NULL);

CloseHandle(hThread1);

CloseHandle(hThread2);

g_hEvent=CreateEvent(NULL,FALSE,FALSE,NULL);   //第二个参数设定FALSE为自动重置事件对象

SetEvent(g_hEvent);  // 把事件对象设置成有信号状态,当然这里也可以通过把CreateEvent的第三个参数设置成TRUE来实现

Sleep(4000);

CloseHandle(g_hEvent);//关闭事件对象句柄

}

DWORD WINAPI Fun1Proc(

LPVOID lpParameter   // thread data

)

{

while(TRUE)

{

WaitForSingleObject(g_hEvent,INFINITE); // 这时候系统会把g_hEvent变成非信号状态

if(tickets>0)

{

Sleep(1);

cout<<"thread1 sell ticket : "<<tickets--<<endl;

}

else

break;

SetEvent(g_hEvent);//重新设置成有信号状态

}

return 0;

}

DWORD WINAPI Fun2Proc(

LPVOID lpParameter   // thread data

)

{

while(TRUE)

{

WaitForSingleObject(g_hEvent,INFINITE);

if(tickets>0)

{

Sleep(1);

cout<<"thread2 sell ticket : "<<tickets--<<endl;

}

else

break;

SetEvent(g_hEvent);

}

return 0;

}

转:VC++线程同步-事件对象的更多相关文章

  1. VC++ 线程同步 总结

    注:所谓同步,并不是多个线程一起同时执行,而是他们协同步调,按预定的先后次序执行. 与线程相关的基本函数包括:CreateThread:创建线程CloseHandle:关闭线程句柄.注意,这只会使指定 ...

  2. 经典线程同步 事件Event

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...

  3. 多线程面试题系列(6):经典线程同步 事件Event

    上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题.首先 ...

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

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...

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

    原文地址:http://blog.csdn.net/morewindows/article/details/7445233 上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的“线程所有权” ...

  6. C#线程学习笔记五:线程同步--事件构造

    本笔记摘抄自:https://www.cnblogs.com/zhili/archive/2012/07/23/Event_Constructor.html,记录一下学习过程以备后续查用. 前面讲的线 ...

  7. MFC线程(三):线程同步事件(event)与互斥(mutex)

    前面讲了临界区可以用来达到线程同步.而事件(event)与互斥(mutex)也同样可以做到. Win32 API中的线程事件 HANDLE hEvent = NULL; void MainTestFu ...

  8. java线程同步以及对象锁和类锁解析(多线程synchronized关键字)

    一.关于线程安全 1.是什么决定的线程安全问题? 线程安全问题基本是由全局变量及静态变量引起的. 若每个线程中对全局变量.静态变量只有读操作,而无写操作,一般来说,这个全局变量是线程安全的:若有多个线 ...

  9. VC++线程同步之临界区(CriticalSection)

    1.相关文件和接口 #include <windows.h> CRITICAL_SECTION cs;//定义临界区对象 InitializeCriticalSection(&cs ...

随机推荐

  1. DevExpress 利用DateEdit 仅显示和选择年份 z

    DevExpress只提供了选择月份的控件MonthEdit,并没提供选择选择年份的控件,目测是官方偷懒不想弄,因为要实现的方法也很简单,利用ComboBoxEdit添加年份数据即可,直接封装一个控件 ...

  2. iOS开发-UIApplication和App启动状态

    UIApplication简单从字面上了解就是应用程序,开发的时候有的时候会根据需要调用其中的方法,看起来不起眼,实际在iOS开发UIApplication提供了iOS程序运行期间的控制和协作工作.每 ...

  3. JavaScript生成GUID的方法

    一.生成GUID的方法一     JScript 代码   复制 function guid() { function S4() { return (((1+Math.random())*0x1000 ...

  4. 架构师书单 2nd Edition

    了2007年的目标,列了下面待读或重读的书单.    "其实中国程序员,现在最需要的是一张安静的书桌.",的确,中国架构师大多缺乏系统的基础知识,与其自欺欺人的宣扬"读书 ...

  5. 【Python】Python 微服务框架 nameko

    nameko: 1.支持服务发现.负载均衡 2.支持依赖自动注入,使用很方便 3.缺点:超时.限速.权限等机制不完善 代码示例:https://github.com/junneyang/nameko- ...

  6. .NET/Mysql-petatoco连接mysql数据库

    安装mysql数据库 用nugget添加.net连接mysql数据库的组件

  7. chm格式文件,win7下用c:/windows/hh.exe打开

    chm格式文件,win7下用c:/windows/hh.exe打开

  8. Mongo读书笔记2 -- 数据类型

      Mongo有多种类型的collection, 默认的是随着document 数目的增多自动增大; 还有一些collection被称为capped collection, 只能包含固定数目的docu ...

  9. 当requestFocus不能立刻起作用时…

    不知道各位有没有遇到过这种情况: 第一次一个apk界面.然后本来想在某处requestFocus()使之获得焦点来显示的,可是直接调用却不行,如图1所看到的. 图1 焦点的位置 出现这种现象是Andr ...

  10. 开源 免费 java CMS - FreeCMS1.9 会员权限管理

    项目地址:http://www.freeteam.cn/ 会员权限管理 管理会员可使用的权限.会员在使用某一特定功能时,如投稿.可依据此会员所在会员组是否有投稿权限来决定会员能否够使用投稿功能. 1. ...