条件变量是允许多个线程相互交流的同步原语。它允许一定量的线程等待(可以定时)另一线程的提醒,然后再继续。条件变量始终关联到一个互斥

定义于头文件 <condition_variable>

condition_variable:

condition_variable 类是同步原语,能用于阻塞一个线程,或同时阻塞多个线程,直至另一线程修改共享变量(条件)并通知 condition_variable 。

有意修改变量的线程必须

  1. 获得 std::mutex (典型地通过 std::lock_guard )
  2. 在保有锁时进行修改
  3. 在 std::condition_variable 上执行 notify_one 或 notify_all (不需要为通知保有锁)

即使共享变量是原子的,也必须在互斥下修改它,以正确地发布修改到等待的线程。

任何有意在 std::condition_variable 上等待的线程必须

  1. 获得 std::unique_lock<std::mutex> ,在与用于保护共享变量者相同的互斥上
  2. 执行 wait 、 wait_for 或 wait_until ,等待操作自动释放互斥,并悬挂线程的执行
  3. condition_variable 被通知时,时限消失或虚假唤醒发生,线程被唤醒,且自动重获得互斥。之后线程应检查条件,若唤醒是虚假的,则继续等待

代码:

 #include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
using namespace std; std::mutex m;
std::condition_variable cv;
string data;
bool ready = false;
bool processed = false; void worker_thread() {
//等待直至 main() 发送数据
std::unique_lock<std::mutex> lk(m);//拥有mutex,并调用mutex.lock()对其上锁
cv.wait(lk, []{return ready;});//等价于 while(!ready) cv.wait(lk);
//在调用 wait 时会自动执行 lk.unlock()
//当 wait 被其它线程唤醒时,锁会自动恢复 wait 之前的状态 //等待后,我们占有锁
cout << "worker thread is processing data\n";
data += " after processing"; //发送数据回 main
processed = true;
cout << "worker thread sigals data processing completed\n"; lk.unlock();//通知前手动解锁,以避免等待线程再阻塞
cv.notify_one();
} int main(void) {
std::thread worker(worker_thread); data = "Example data";
//发送数据到worker线程
{
std::lock_guard<std::mutex> lk(m);
ready = true;
cout << "main() sigals data ready for processing\n";
}
cv.notify_one(); //等候worker
{
std::unique_lock<std::mutex> lk(m);
cv.wait(lk, []{return processed;});//等价于while(!processed) cv.wait(lk)
}
cout << "Back in main(), data = " << data << '\n'; worker.join(); // 输出:
// main() sigals data ready for processing
// worker thread is processing data
// worker thread sigals data processing completed
// Back in main(), data = Example data after processing return ;
}

注意:虚假唤醒问题 https://segmentfault.com/q/1010000010421523/a-1020000010457503

https://blog.csdn.net/shizheng163/article/details/83661861

condition_variable_any 类是 std::condition_variable 的泛化。相对于只在 std::unique_lock<std::mutex> 上工作的 std::condition_variable , condition_variable_any 能在任何满足基础可锁 (BasicLockable) 要求的锁上工作,操作和 std::condition_variable 完全相同

c++多线程基础4(条件变量)的更多相关文章

  1. linux多线程同步pthread_cond_XXX条件变量的理解

    在linux多线程编程中,线程的执行顺序是不可预知的,但是有时候由于某些需求,需要多个线程在启动时按照一定的顺序执行,虽然可以使用一些比较简陋的做法,例如:如果有3个线程 ABC,要求执行顺序是A-- ...

  2. linux C++ 多线程使用pthread_cond 条件变量

    1. 背景 多线程中经常需要使用到锁(pthread_mutex_t)来完成多个线程之间的互斥操作. 但是互斥锁有一个明显到缺点: 只有两种状态,锁定和非锁定. 而条件变量则通过允许线程阻塞并等待另一 ...

  3. Linux多线程编程的条件变量

    在stackoverflow上看到一关于多线程条件变量的问题,题主问道:什么时候会用到条件变量,mutex还不够吗?有个叫slowjelj的人做了很好的回答,我再看这个哥们其他话题的一些回答,感觉水平 ...

  4. 练习生产者与消费者-PYTHON多线程中的条件变量同步-Queue

    以前练习过,但好久不用,手生,概念也生了, 重温一下.. URL: http://www.cnblogs.com/holbrook/tag/%E5%A4%9A%E7%BA%BF%E7%A8%8B/ ~ ...

  5. Linux 多线程编程—使用条件变量实现循环打印

    编写一个程序,开启3个线程,这3个线程的ID分别为A.B.C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示:如:ABCABC….依次递推. 使用条件变量来实现: #inc ...

  6. 多线程编程中条件变量和的spurious wakeup 虚假唤醒

    1. 概述 条件变量(condition variable)是利用共享的变量进行线程之间同步的一种机制.典型的场景包括生产者-消费者模型,线程池实现等. 对条件变量的使用包括两个动作: 1) 线程等待 ...

  7. python多线程编程5: 条件变量同步-乾颐堂

    互斥锁是最简单的线程同步机制,Python提供的Condition对象提供了对复杂线程同步问题的支持.Condition被称为条件变量,除了提供与Lock类似的acquire和release方法外,还 ...

  8. Java多线程基础——对象及变量并发访问

    在开发多线程程序时,如果每个多线程处理的事情都不一样,每个线程都互不相关,这样开发的过程就非常轻松.但是很多时候,多线程程序是需要同时访问同一个对象,或者变量的.这样,一个对象同时被多个线程访问,会出 ...

  9. java多线程技术之条件变量

    上一篇讲述了并发包下的Lock,Lock可以更好的解决线程同步问题,使之更面向对象,并且ReadWriteLock在处理同步时更强大,那么同样,线程间仅仅互斥是不够的,还需要通信,本篇的内容是基于上篇 ...

随机推荐

  1. Java对网络图片/本地图片转换成Base64编码和解码

    一.将本地图片转换成Base64编码字符串 /** * 将本地图片转换成Base64编码字符串 * * @param imgFile 图片目录路径 * @return */ public static ...

  2. 使用Handler类来更新UI

    在android里面,我们经常要上网获取一些数据,然后更新UI,但获取数据是要时间的,如果在主线程里面直接使用获取数据的代码的话.整个activity就会卡在那,直至你获取到数据更新完UI才会加载完成 ...

  3. sonarLint 插件配置sonarQube Server

    Connected Mode You can bind Eclipse projects to a SonarQube project (supporting SonarQube servers 5. ...

  4. swift之弹出一个背景半透明的UIViewController

    坑爹的背景半透明,按网上给出oc的方法,动画结束之后,半透明效果消失.通过各种折腾,各种试验,终于搞定了. let viewController=storyboard.instantiateViewC ...

  5. JS事件冒泡和事件捕获的详解

    在学校,听老师讲解事件冒泡和事件捕获机制的时候跟听天书一样,只依稀记得IE使用的是事件冒泡,其他浏览器则是事件捕获.当时的我,把它当成IE浏览器兼容问题,所以没有深究(IE8以下版本的浏览器已基本退出 ...

  6. LoadRunner 关联和集合点、检查点

    1)关联的定义 很多时候,当时录完之后,没有问题.过一段时间再跑脚本,就不会成功.比如session,过期了,再一次使用,就会出错.这个时候,需要在每次访问的时候动态的拿到session,这种情况就需 ...

  7. php析构方法关于栈的问题

    <?php class test{ var $name; var $sex; var $age; function __construct( $name, $sex ,$age ) { $thi ...

  8. jQuery基础,选择器

    jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架).jQuery设计的宗旨是“write Less, ...

  9. Docker学习之路(三)Docker网络详解

    1. Docker的4种网络模式 我们在使用docker run创建Docker容器时,可以用--net选项指定容器的网络模式,Docker有以下4种网络模式: host模式,使用--net=host ...

  10. Map-making Robots: A Review of the Occupancy Grid Map Algorithm

    栅格地图算法:http://www.ikaros-project.org/articles/2008/gridmaps/