前言:发出消息的线程叫做检测线程,响应消息的线程称为响应线程。

C++11线程间的通信方式有三种:

(1)通过条件变量进行线程间的通信

(2)通过标志位来通知线程间的通信

(3)通过std::furture来进行线程间的通信

  • (1)通过条件变量进行线程间的通信

全局区间中定义如下:

std::condition_variable cv;// condvar for event

std::mutex m;//mutex for use with cv

检测线程中代码如下:

cv.notify_one();//如果有多个响应线程则使用notify_all代替notify_one.

响应线程中代码如下:

std::unique_lock<std::mutex> lk(m)//lock mutex

cv.wait(lk);//这是有缺陷的语句

缺陷:

  • 如果检测线程在响应线程等待之前通知condvar,那么响应线程会永远的进行挂起,也就是说:如果检测线程在响应线程执行等待之前就已经执行了通知,那么响应线程就会错过通知,并永远的等待下去。
  • 条件变量的wait无法避免伪唤醒。(伪唤醒:线程API的等待即使没有通知condvar,等待条件变量的代码也有可能被唤醒)一般使用lambda来避免伪唤醒的情况。

cv.wait(lk,[]{return whether the event has occurred;});//利用这种能力来要求响应线程能够确定它等待的条件是否为真。

  • (2)使用共享布尔标志来进行线程间的通信

全局区间中的定义如下:

std::atomic<bool> flag(false);  //shared flag

flag = true;//tall reacting thread

响应线程只是简单的轮询标志,当它看到标志为true时,它知道等待的事件已经发生。

white(!flag);//wait for event

这种方法没有互斥变量也没有伪唤醒。不足之处就是响应线程中的轮询的成本。(也就是说占用了硬件线程)

  • (3)综上两种的结合

我们通常将condvar和基于标志的设计组合使用。标志指示感兴趣的事件是否已经发生,而对标志的访问是由互斥锁同步的,由于互斥阻止对标志的并发访问,不需要将标志声明为std::atomic,一个简单的bool就可以。

全局区间:

Std::conditional_variable cv;

Std::mutex m;

检测线程:

Bool flag(false);//not atomic

{

std::lock_guard<std::mutex> lg;

Flag = true;

}

cv.notify_one;//tell reactive thread

响应线程:

std::unique_lock<std::mutex> lk(m);

cv.wait(lk,[]{return flag;};//use lambda to avoid 伪唤醒

这种方法避免了上述所有的缺点,但是依然比较笨拙。

  • (4)让响应线程wait由检测线程设置的future,从而避免使用条件变量、互斥锁和标志

future表征的是从被调用者到(异步)调用者的通信通道的接收端,在这里,检测和响应线程之间没有被调用者与调用者关系。发送端为std::promise且接受端为future的通信信道不仅可跨线程,还易用用与任何需要将信息从程序中的一个位置传输到另一个位置的情况。例如:

在全局作用域下:

Std::promise<void> p;//promise for communication channel

检测线程的作用域下:

p.set_value();//tell reactinve task

响应线程的作用域下:

p.get_future().wait();//wat on future corresponding to p

优点:不需要互斥锁,不管检测线程是否在响应任务等待之前设置了std::promise,它都能正常工作,不受伪唤醒影响(只有条件变量才有伪唤醒),等待时不消耗硬件系统资源。

缺点:std::promise只能设置一次,std::promise和future之间的通信通道是一个一次性的机制。

C++11 线程通信的三种方式相关推荐

  1. java线程通信的三种方式

    1.传统的线程通信. 在synchronized修饰的同步方法或者修饰的同步代码块中使用Object类提供的wait(),notify()和notifyAll()3个方法进行线程通信. 关于这3个方法 ...

  2. linux+Qt 下利用D-Bus进行进程间高效通信的三种方式

    linux+Qt 下利用D-Bus进行进程间高效通信的三种方式 原文链接: https://www.cnblogs.com/wwang/archive/2010/10/27/1862552.html ...

  3. 一心多用多线程-线程创建的三种方式

    第一次了解java线程机制,记录一下线程启动的三种方式. 1.通过继承Thread类调用一个线程 public class Thread1 extends Thread{@Overridepublic ...

  4. JUC-多线程(5.获得线程的第三种方式)学习笔记

    文章目录 获得线程的第三种方式 : Callable接口 1. 前言 1. 获得多线程的方法几种? 2. 以下两种获得线程的方式的异同 2. 使用 1. 重写 call 方法 2.创建线程 3.获取返 ...

  5. 创建线程的第三种方式---JDK8新特性

    创建线程的第三种方式-JDK8新特性 实现Callable接口,创建线程 Runnable和Callable接口的不同 1.Callable可以返回一个类型V,而Runnable不可以,也就是说Cal ...

  6. 创建线程的第三种方式:实现Callable接口(含部分源码解析)

    创建线程的第三种方式--实现Callable接口 package com.lqy.Multithreading; import java.util.concurrent.Callable; impor ...

  7. 容器间通信的三种方式 - 每天5分钟玩转 Docker 容器技术(35)

    容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信. IP 通信 从上一节的例子可以得出这样一个结论:两个容器要能通信,必须要有属于同一个网络的网卡. 满足这 ...

  8. docker(5、网络2) 1、容器间通信的三种方式 2、 容器如何访问外部 3、 外部如何访问容器

    1.容器之间可通过 IP,Docker DNS Server 或 joined 容器三种方式通信 自定义网络 根据业务需要可通过 bridge 驱动创建类似前面默认的 bridge 网络 1.自定义网 ...

  9. java实现线程安全的三种方式

    前言 一个程序在运行起来的时候会转换成进程,通常含有多个线程.通常情况下,一个进程中的比较耗时的操作(如长循环.文件上传下载.网络资源获取等),往往会采用多线程来解决. 比如现实生活中,银行取钱问题. ...

最新文章

  1. C++语言基本类型—浮点型
  2. centos6.5下部署用于生产的hadoop,并使用C语言API连接hadoop
  3. mac 上搭建gitlabel_在mac终端中使用git(适用于github、gitlabel)
  4. C++游戏开发需要阅读的书籍
  5. PAT_B_1047_Java(20分)
  6. 计算机运维知识点,系统运维必会知识点
  7. dateframe行列插入和删除操作
  8. 关于fetch api这点事
  9. djnago seeeion
  10. 米家扫地机器人是石头代工_扫地机器人“两强”突进,选科沃斯还是石头科技?...
  11. linux 文件大小 自动变化 写,Linux下自动清理超过指定大小文件的方法
  12. (译)iOS Code Signing: 解惑
  13. Mac配置vscode ssh远程连接主机(远程办公必备)
  14. 社交app的变现方式有哪些?
  15. Unity 增加2D游戏的打击感笔记
  16. 教你 用c语言输出乘法口诀表 一giao我嘞gaiogiao
  17. 旷视科技1面2面----最差的一次面试体验
  18. 王爽版汇编语言实验7 寻址方式在结构化数据访问中的应用
  19. 【Docker镜像文件加载原理生产中重新制作并提交镜像文件案例演示】
  20. 移动互联网的黄金时代,真的结束了

热门文章

  1. 7、android高级控件(2)(列表类视图)
  2. 腾讯、百度、网易游戏、华为Offer及笔经面经
  3. 2023年1月23日--2023年1月29日(osg+glsl+socket+ue,本周20小时,合计1899小时,剩余8101小时)
  4. 华为云计算IE面试笔记-其它知识点
  5. 第11课:五大职能定位
  6. 很多人都在换苹果原装电池,那么原装电池是哪个厂商生产的?
  7. stm32f103c8t6 TIM2定时器1ms中断
  8. 画图说明计算机控制系统的硬件组成,2019年4月自学考试微机控制技术真题
  9. PTA 实例1.1:最大子列和问题
  10. python爬虫原理和运营商SDK数据建模抓取的区别