<一>事件

事件主要用于线程间传递消息,通过事件来控制一个线程是处于执行状态还是处于挂起状态。

事件和互斥量之间的差别:

  1. 事件主要用于协调两个或者多个线程之间的动作,使其协调一致,符合逻辑。一个线程等待某个事件的发生,另一个线程则在事件发生后产生一个信号,通知那个正在等待的线程(我的理解:线程A等待键盘输入,线程B在有键盘输入后发送一个信号给A,使得A可以执行,事件就是“键盘输入”)。
  2. 互斥量主要是为了保证在任何时刻只有一个线程在使用共享资源,线程的运行次序是随机的,有操作系统决定,因此互斥量不能使两个线程按一定的顺序执行。
  3. 互斥量有信号状态是指线程正在拥有该互斥量,无信号是指没有线程拥有这个互斥量;对事件来说,当等待的事件发生时,事件对象处于活动状态,叫有信号状态,相反的,当等待的事件没有发生时,事件对象处于无信号状态。
  4. 事件一般分为两种:手动事件和自动事件。手动事件是指当事件对象处于活动状态时它会一直处于这个状态,直到显示地将其置为无信号状态;自动事件是指当事件处于有信号状态并有一个线程接收到该事件后,事件立即变为无信号状态。

<二>与事件有关的函数

函数名 作用
CreateEvent 创建一个事件
OpenEvent 打开一个已经创建的事件
SetEvent 触发一个事件
ResetEvent 复位一个事件
PulseEvent 触发并重置一个事件
WaitForSingleObject 等待单个事件
WaitForMultipleObject 等待多个事件
#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <iostream>
#include <fstream>
using namespace std; HANDLE hEvent; unsigned long _stdcall MyThread1(LPVOID lpParam)
{
cout<<"Wait for event\n";
WaitForSingleObject(hEvent,INFINITE);
cout<<"Get the event\n";
return ;
} unsigned long _stdcall MyThread2(LPVOID lpParam)
{
Sleep();
cout<<"Signal the event\n";
SetEvent(hEvent);
return ;
} int main()
{
HANDLE handle1,handle2;
DWORD dw1,dw2;
hEvent = CreateEvent(NULL,FALSE,FALSE,NULL);
handle1 =CreateThread(NULL,NULL,MyThread1,NULL,NULL,&dw1);
handle2 =CreateThread(NULL,NULL,MyThread2,NULL,NULL,&dw2); Sleep(); CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(hEvent); return ;
}

再看一个难一点的例子:两个读线程,一个写线程。

#include <windows.h>
#include <process.h> /* _beginthread, _endthread */
#include <iostream>
#include <fstream>
using namespace std; HANDLE hWriteEvent;
HANDLE hReadEvent[]; int buff[]; CRITICAL_SECTION cs;
BOOL isRunning = true; unsigned long _stdcall WriteThread(LPVOID lpParam)
{
hWriteEvent = CreateEvent(NULL,TRUE,FALSE,NULL);//创建一个写事件,并处于有信号状态
int k = ;
while (isRunning)
{
if(WAIT_OBJECT_0==WaitForMultipleObjects(,hReadEvent,true,))
{
for (int i = ;i<;i++)
{
buff[i]=(i+)*k;
}
k++;
PulseEvent(hWriteEvent);
}
}
return ;
} unsigned long _stdcall ReadThread1(LPVOID lpParam)
{
hReadEvent[] = CreateEvent(NULL,FALSE,TRUE,NULL);
while (isRunning)
{
WaitForSingleObject(hWriteEvent,INFINITE);
EnterCriticalSection(&cs);
cout<<"Print from Thread #1:";
for (int i = ;i<;i++)
cout<<buff[i]<<" "; cout<<endl;
LeaveCriticalSection(&cs);
SetEvent(hReadEvent[]); }
return ;
} unsigned long _stdcall ReadThread2(LPVOID lpParam)
{
hReadEvent[] = CreateEvent(NULL,FALSE,TRUE,NULL);
while (isRunning)
{
WaitForSingleObject(hWriteEvent,INFINITE);
EnterCriticalSection(&cs);
cout<<"Print from Thread #2:";
for (int i = ;i<;i++)
cout<<buff[i]<<" "; cout<<endl;
LeaveCriticalSection(&cs);
SetEvent(hReadEvent[]); }
return ;
} unsigned long _stdcall ControlThread(LPVOID lpParam)
{
isRunning = FALSE;
return ;
} int main()
{
HANDLE handle1,handle2,handle3,handle4;
DWORD dw1,dw2,dw3,dw4;
InitializeCriticalSection(&cs); handle1 = CreateThread(NULL,,WriteThread,NULL,,&dw1);
handle2 = CreateThread(NULL,,ReadThread1,NULL,,&dw2);
handle3 = CreateThread(NULL,,ReadThread2,NULL,,&dw3);
Sleep();
handle4 = CreateThread(NULL,,ControlThread,NULL,,&dw4); CloseHandle(handle1);
CloseHandle(handle2);
CloseHandle(handle3);
CloseHandle(handle4);
CloseHandle(hWriteEvent);
CloseHandle(hReadEvent[]);
CloseHandle(hReadEvent[]); return ;
}

Windows环境下多线程编程原理与应用读书笔记(7)————事件及其应用的更多相关文章

  1. Windows环境下多线程编程原理与应用读书笔记(1)————基本概念

    自从学了操作系统知识后,我就对多线程比较感兴趣,总想让自己写一些有关多线程的程序代码,但一直以来,发现自己都没怎么好好的去全面学习这方面的知识,仅仅是完成了操作系统课程上的小程序,对多线程的理解也不是 ...

  2. Windows环境下多线程编程原理与应用读书笔记(3)————Windows环境中的多线程实现(3)

    纤程 纤程(fiber): 相当于用户级别的线程或轻进程.纤程由Win32库函数支持,对核心是不可见的.纤程可以通过SwitchToFiber显示至另一合作纤程,以实现合作纤程之间的协同.线程是在Wi ...

  3. Windows环境下多线程编程原理与应用读书笔记(8)————信号量及其应用

    <一>线程间同步原因 线程间竞争共享资源: 线程间为完成某个任务而协作: 通过互斥量可以实现线程间由于竞争所需要的同步,通过事件可以实现线程间由于协作所需要的同步. 信号量很好地将互斥量和 ...

  4. Windows环境下多线程编程原理与应用读书笔记(6)————临界段及其应用

    <一>临界段 临界段对象通过提供所有线程必须共享的对象来控制线程.只有拥有临界段对象的线程才能够访问保护的资源.在另一个线程可以访问该资源之前,前一线程必须释放临界段对象,一遍新的线程可以 ...

  5. Windows环境下多线程编程原理与应用读书笔记(5)————互斥及其应用

    <一>互斥的同步机制 思想:当一个线程获得互斥量了后,其他所有要获取同一个互斥量的线程都处于阻塞状态,直到第一个线程释放互斥量为止. 设想几个线程竞争同一个互斥量,其中一个线程获得了互斥量 ...

  6. Windows环境下多线程编程原理与应用读书笔记(2)————面向对象技术

    面向对象技术是学C++需要重点掌握的知识,因为我觉得自己的基础还是比较可以,这一章节的内容就只是粗略的读了一遍,在此就不做过多的笔记.

  7. Windows环境下多线程编程原理与应用读书笔记(4)————线程间通信概述

    <一>线程间通信方法 全局变量方式:进程中的线程共享全局变量,可以通过全局变量进行线程间通信. 参数传递法:主线程创建子线程并让子线程为其服务,因此主线程和其他线程可以通过参数传递进行通信 ...

  8. Java多线程编程实战指南 设计模式 读书笔记

    线程设计模式在按其有助于解决的多线程编程相关的问题可粗略分类如下. 不使用锁的情况下保证线程安全: Immutable Object(不可变对象)模式.Thread Specific Storage( ...

  9. 关于docker在windows环境下运行的第一次体验

    关于docker在windows环境下执行的原理 1.1.           首先是Docker Quickstart启动,如果在虚拟机Oracle VM VirtualBox不存在default虚 ...

随机推荐

  1. 【SQL】- 基础知识梳理(六) - 游标

    游标的概念 结果集,结果集就是select查询之后返回的所有行数据的集合. 游标(Cursor): 是处理数据的一种方法. 它可以定位到结果集中的某一行,对数据进行读写. 也可以移动游标定位到你需要的 ...

  2. SQL性能优化十条经验(转)

    1.查询的模糊匹配 尽量避免在一个复杂查询里面使用 LIKE '%parm1%'-- 红色标识位置的百分号会导致相关列的索引无法使用,最好不要用. 解决办法: 其实只需要对该脚本略做改进,查询速度便会 ...

  3. OpenStack Pike超详细搭建文档 LinuxBridge版

    前言 搭建前必须看我 本文档搭建的是分布式P版openstack(1 controller + N compute + 1 cinder)的文档. openstack版本为Pike. 搭建的时候,请严 ...

  4. struts2---自定义类型转换器

    从servlet我们知道从页面获取到的参数都是string类型,但是struts2中基本的数据类型,它可以自动帮我们转化为其对应的包装类,就像获取到123,可以自动转化为Integer,但是比如201 ...

  5. linux视频之media媒体框架

    linux视频媒体(kernel层分析)主要包括三个文件: (/drivers/media/media-device.c ,  /drivers/media/media-devnode.c , /dr ...

  6. Elixir游戏服设计四

    上章说到我们要引入syn https://github.com/ostinelli/syn/ 看过文档,它并没有直接提供{via, Module, Name} 相关的方法.我们需要封装一下. Name ...

  7. ZOJ2965 Accurately Say "CocaCola"! 线性扫描

    Accurately Say "CocaCola"! 范围找到:1--700左右,然后打表就ok了 #include<cstdio> #include<cstdl ...

  8. ubuntu环境下lnmp环境搭建(2)之Nginx

    1. ubuntu编译安装nginx http://www.cnblogs.com/zhangjun516/archive/2013/02/03/2890990.html 1. 手动编译安装 Ngin ...

  9. sqlserver 使用脚本创建Sql Server代理作业

    use master GO /* --开启sql server代理 sp_configure 'show advanced options', 1; GO RECONFIGURE; GO sp_con ...

  10. 项目收集-AutoMapper使用,事务,Json.Net序列化反序列化,代码生成调用等

    using System; using AutoMapper; using Newtonsoft.Json; using Newtonsoft.Json.Linq; namespace Console ...