事件和互斥体同样属于内核同步对象,它和互斥体以及临界区在功能上有以下区别

前面的互斥体和临界区主要作用在于确保控制多个线程之间对共享资源访问,保证共享资源的完整性

事件主要作用是通知其它线程一个操作己经完成,可以接下来执行后面剩余操作了,确保多个线程之间的动作以指定的次序发生

例如:一个线程A用于初始化,一个线程B等待线程A初始化后执行后续操作。

当线程A初始化完成后设置线程B等待的事件为己通知状态,此时线程B从等待函数中得到事件己通知状态,就可以知道线程A己经执行完初始化操作,线程B开始执行后续操作

包含三个部份:

使用计数器: 所有内核对象都有这个属性

事件重置类型: 人工重置为TRUE,自动重置为FALSE

通知状态: 通知状态为TRUE,未通知状态为FALSE

注意:事件有一些特殊的地方,根据创建事件时使用自动重置还是人工重置,程序行为就有很大的差别

事件是人工重置时当得到通知,等待该事件的所有线程均变为可调度线程。而事件是自动重置时得到通知,等待该事件的线程中只有一个线程变为可调度线程

创建事件对象

HANDLE CreateEvent(PSECURITY_ATTRIBUTES psa, BOOL fManualReset, BOOL fInitialState, PCTSTR pszName);

1.psa     指向安全属性指针,一般为NULL

2.fManualReset   事件重置类型,人工重置为TRUE,自动重置为FALSE

3.fInitialState   初始化事件状态,通常为FALSE未通知状态

4.pszName  指定事件对象的名称

返回值:

成功返回新事件对象句柄,失败返回0

注意:如果己经有同名的事件对象存在,函数将返回己有的事件对象句柄,不会再创建新的事件对象

设置事件为己通知状态

BOOL SetEvent(HANDLE hEvent);

设置事件为己通知状态

BOOL ResetEvent(HANDLE hEvent);

编写一个Demo用于演示Event事件基本操作

功能介绍:

程序启动时创建三个线程,线程A B C.  先执行线程A,然后执行线程B,然后执行线程C

线程A执行初始化操作,给全局数组赋值大写字母A-E,然后通知线程B,线程B再把全局数组中所有字母改为小写a-e, 然后通知线C,线程C最后把全局数组中所有字母倒置

开始编写代码:

1. 创建个基于对话框的工程EventDemo

2. 添加一个编辑框用于显示信息,修改ID为IDC_EDIT_SHOWINFO, 修改属性为不可读.

3. 定义相关全局变量和线程函数前置声明

 char g_szData[] = {};
CEdit* g_pEdit;
HANDLE g_eventInit; //初始化事件
HANDLE g_eventBigToSmall; //大写转小写事件
HANDLE g_eventReverse; //倒置事件 //线程函数前置声明
DWORD WINAPI Thread_Init(LPVOID lpParam);
DWORD WINAPI Thread_BigToSmall(LPVOID lpParam);
DWORD WINAPI Thread_Reverse(LPVOID lpParam);

全局变量和线程函数前置声明

4. OnInitDialog中添加相应代码

 BOOL CEventDemoDlg::OnInitDialog()
{
CDialogEx::OnInitDialog(); // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动
// 执行此操作
SetIcon(m_hIcon, TRUE); // 设置大图标
SetIcon(m_hIcon, FALSE); // 设置小图标 //创建三个事件
g_eventInit = CreateEvent(NULL,FALSE,FALSE,NULL);
g_eventBigToSmall = CreateEvent(NULL,FALSE,FALSE,NULL);
g_eventReverse = CreateEvent(NULL,FALSE,FALSE,NULL);
//保存下编辑框指针供线程内部使用
g_pEdit = (CEdit*)GetDlgItem(IDC_EDIT_SHOWINFO);
//创建三个线程
CloseHandle(CreateThread(NULL,,Thread_Init,NULL,,NULL));
CloseHandle(CreateThread(NULL,,Thread_BigToSmall,NULL,,NULL));
CloseHandle(CreateThread(NULL,,Thread_Reverse,NULL,,NULL)); //设置第一件事件为通知状态
SetEvent(g_eventInit); return TRUE; // 除非将焦点设置到控件,否则返回 TRUE
}

OnInitDialog

5.三个线程代码

 DWORD WINAPI Thread_Init(LPVOID lpParam)
{
WaitForSingleObject(g_eventInit,INFINITE);
//赋值五个大写字母A-E
g_szData[] = 'A';
g_szData[] = 'B';
g_szData[] = 'C';
g_szData[] = 'D';
g_szData[] = 'E';
//编辑框输出下相关信息
CString str;
g_pEdit->GetWindowText(str);
str += _T("线程_初始化:");
for (int i=; i<sizeof(g_szData); i++)
{
str += g_szData[i];
}
str += _T("\r\n");
g_pEdit->SetWindowText(str);
//设置为未通知状态
ResetEvent(g_eventInit);
//设置大写转小写事件为通知状态
SetEvent(g_eventBigToSmall);
return TRUE;
}

线程_初始化

 DWORD WINAPI Thread_BigToSmall(LPVOID lpParam)
{
WaitForSingleObject(g_eventBigToSmall,INFINITE);
//大写转小写
for (int i = ; i<sizeof(g_szData); i++)
{
g_szData[i] = g_szData[i] + ;
}
//编辑框输出下相关信息
CString str;
g_pEdit->GetWindowText(str);
str += _T("线程_大写转小写:");
for (int i=; i<sizeof(g_szData); i++)
{
str += g_szData[i];
}
str += _T("\r\n");
g_pEdit->SetWindowText(str);
//设置为未通知状态
ResetEvent(g_eventBigToSmall);
//设置倒置事件为通知状态
SetEvent(g_eventReverse);
return TRUE;
}

线程_大写转小写

 DWORD WINAPI Thread_Reverse(LPVOID lpParam)
{
WaitForSingleObject(g_eventReverse,INFINITE);
//倒置
int i = ;
int j = sizeof(g_szData) - ;
int temp = ;
for (;i<j;i++,j--)
{
temp = g_szData[i];
g_szData[i] = g_szData[j];
g_szData[j] = temp;
}
//编辑框输出下相关信息
CString str;
g_pEdit->GetWindowText(str);
str += _T("线程_倒置:");
for (i=; i<sizeof(g_szData); i++)
{
str += g_szData[i];
}
str += _T("\r\n");
str += _T("程序执行完毕\r\n");
g_pEdit->SetWindowText(str);
//设置为未通知状态
ResetEvent(g_eventReverse);
return TRUE;
}

线程_倒置

6.DestroyWindow添加相应代码

 BOOL CEventDemoDlg::DestroyWindow()
{
CloseHandle(g_eventInit);
CloseHandle(g_eventBigToSmall);
CloseHandle(g_eventReverse); return CDialogEx::DestroyWindow();
}

DestroyWindow

最终演示效果如下:

多线程(五)多线程同步_Event事件的更多相关文章

  1. {python--GIL锁}一 介绍 二 GIL介绍 三 GIL与Lock 四 GIL与多线程 五 多线程性能测试

    python--GIL锁 GIL锁 本节目录 一 介绍 二 GIL介绍 三 GIL与Lock 四 GIL与多线程 五 多线程性能测试 一 背景知识 ''' 定义: In CPython, the gl ...

  2. php Pthread 多线程 (五) 线程同步

    有些时候我们不希望线程调用start()后就立刻执行,在处理完我们的业务逻辑后在需要的时候让线程执行. <?php class Sync extends Thread { private $na ...

  3. C#多线程之线程同步篇2

    在上一篇C#多线程之线程同步篇1中,我们主要学习了执行基本的原子操作.使用Mutex构造以及SemaphoreSlim构造,在这一篇中我们主要学习如何使用AutoResetEvent构造.Manual ...

  4. Linux多线程编程——多线程与线程同步

    多线程 使用多线程好处: 一.通过为每种事件类型的处理单独分配线程,可以简化处理异步事件的代码,线程处理事件可以采用同步编程模式,启闭异步编程模式简单 二.方便的通信和数据交换 由于进程之间具有独立的 ...

  5. C#简单多线程使用(同步和优先权)

    题目: 麦当劳有两个做汉堡的厨师(工号:11,12)和三个销售人员(工号:21,22,23). 厨师生产汉堡,并负责将做好的汉堡放入货架,货架台大小有限,最多放6个汉堡,11和12不能同时往货架台上放 ...

  6. 多线程(五) java的线程锁

    在多线程中,每个线程的执行顺序,是无法预测不可控制的,那么在对数据进行读写的时候便存在由于读写顺序多乱而造成数据混乱错误的可能性.那么如何控制,每个线程对于数据的读写顺序呢?这里就涉及到线程锁. 什么 ...

  7. python 多进程/多线程/协程 同步异步

    这篇主要是对概念的理解: 1.异步和多线程区别:二者不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段.异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事 ...

  8. C# 多线程之线程同步

    多线程间应尽量避免同步问题,最好不要线程间共享数据.如果必须要共享数据,就需要使用同步技术,确保一次只有一个线程访问和改变共享状态. 一::lock语句 lock语句事设置锁定和接触锁定的一种简单方法 ...

  9. MFC——9.多线程与线程同步

    Lesson9:多线程与线程同步 程序.进程和线程是操作系统的重点,在计算机编程中.多线程技术是提高程序性能的重要手段. 本文主要解说操作系统中程序.进程和线程之间的关系,并通过相互排斥对象和事件对象 ...

随机推荐

  1. ShiroUtil 对密码进行加密

    ShiroUtil 对密码进行加密 package com.mozq.sb.shiro02.config; import org.apache.shiro.authc.SimpleAuthentica ...

  2. ionic4 组件调用的坑

    我们再开发过程中很多模块做成组件,那么调用的时候则需把module.ts中的引入去掉,如下红色框框:

  3. ES6 Set求两个数组的并集、交集、差集;以及对数组去重

    并集: const arr1 = [1, 2, 3, 2, 5]; const arr2 = [1, 4, 6, 8, 3]; // 将两个数组合并 const concatArr = [...arr ...

  4. <DP> (高频)139 375 374 (DP hard)312

    139. Word Break 返回结果较为简单可用dp, 复杂用dfs class Solution { public boolean wordBreak(String s, List<Str ...

  5. 重构 改善既有代码的设计 (Martin Fowler 著)

    第1章 重构, 第一个案例 1.1 起点 1.2 重构的第一步 1.3 分解并重组 statement() 1.4 运用多态取代与价格相关的条件逻辑 1.5 结语 第2章 重构原则 2.1 何谓重构 ...

  6. 重构与模式 (Joshua Kerievsky 著)

    第1章 本书的写作缘由 第2章 重构 第3章 模式 第4章 代码坏味 第5章 模式导向的重构目录 第6章 创建 第7章 简化 第8章 泛化 第9章 保护 第10章 聚集操作 第11章 实用重构 参考文 ...

  7. golang基础之初识

    golang 简介 很久以前,有一个IT公司,这公司有个传统,允许员工拥有20%自由时间来开发实验性项目.在2007的某一天,公司的几个大牛,正在用c++开发一些比较繁琐但是核心的工作,主要包括庞大的 ...

  8. centos 安装python3.7

    先安装依赖包: yum -y install bzip2 bzip2-devel ncurses openssl openssl-devel openssl-static xz lzma xz-dev ...

  9. Java Exception 异常处理

    一.定义 异常(Exception) : 是指程序运行时出现的非正常情况,是特殊的运行错误对象,对应着Java语言特定的运行错误处理机制. 二.两大常见的异常类型 • RuntimeException ...

  10. Vue.js 源码分析(十八) 指令篇 v-for 指令详解

    我们可以用 v-for 指令基于一个数组or对象来渲染一个列表,有五种使用方法,如下: <!DOCTYPE html> <html lang="en"> & ...