std::condition_variable

条件变量std::condition_variable有wait和notify接口用于线程间的同步。如下图所示,Thread 2阻塞在wait接口,Thread 1通过notify接口通知Thread 2继续执行。

具体参见示例代码:

#include<iostream>
#include<mutex>
#include<thread>
#include<queue>
std::mutex mt;
std::queue<int> data;
std::condition_variable cv;
auto start=std::chrono::high_resolution_clock::now(); void logCurrentTime()
{
auto end = std::chrono::high_resolution_clock::now();
auto elapsed = std::chrono::duration_cast<std::chrono::milliseconds>(end - start).count();
std::cout << elapsed << ":";
}
void prepare_data()
{
logCurrentTime();
std::cout << "this is " << __FUNCTION__ << " thread:" << std::this_thread::get_id() << std::endl;
for (int i = 0; i < 10; i++)
{
data.push(i);
logCurrentTime();
std::cout << "data OK:" << i << std::endl;
}
//start to notify consume_data thread data is OK!
cv.notify_one();
} void consume_data()
{
logCurrentTime();
std::cout << "this is: " << __FUNCTION__ << " thread:" << std::this_thread::get_id() << std::endl;
std::unique_lock<std::mutex> lk(mt);
//wait first for notification
cv.wait(lk); //it must accept a unique_lock parameter to wait while (!data.empty())
{
logCurrentTime();
std::cout << "data consumed: " << data.front() << std::endl;
data.pop();
}
} int main()
{
std::thread t2(consume_data);
//wait for a while to wait first then prepare data,otherwise stuck on wait
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::thread t1(prepare_data);
t1.join();
t2.join();
return 0;
}

输出结果

分析

主线程中另启两个线程,分别执行consume_data和prepare_data,其中consume_data要先执行,以保证先等待再通知,否则若先通知再等待就死锁了。首先consume_data线程在从wait 处阻塞等待。后prepare_data线程中依次向队列写入0-10,写完之后通过notify_one 通知consume_data线程解除阻塞,依次读取0-10。

std::future

std::future与std::async配合异步执行代码,再通过wait或get接口阻塞当前线程等待结果。如下图所示,Thread 2中future接口的get或wait接口会阻塞当前线程,std::async异步开启的新线程Thread1执行结束后,将结果存于std::future后通知Thread 1获取结果后继续执行.

具体参见如下代码:

#include <iostream>
#include <future>
#include<thread> int test()
{
std::cout << "this is " << __FUNCTION__ << " thread:" << std::this_thread::get_id() << std::endl;;
std::this_thread::sleep_for(std::chrono::microseconds(1000));
return 10;
}
int main()
{
std::cout << "this is " <<__FUNCTION__<<" thread:" << std::this_thread::get_id() << std::endl;;
//this will lanuch on another thread
std::future<int> result = std::async(test); std::cout << "After lanuch a thread: "<< std::this_thread::get_id() << std::endl; //block the thread and wait for the result
std::cout << "result is: " <<result.get()<< std::endl; std::cout << "After get result "<< std::endl; return 0;
}

输出结果

分析

主程序中调用std::async异步调用test函数,可以看到main函数的线程ID 27428与test函数执行的线程ID 9704并不一样,说明std::async另起了一个新的线程。在test线程中,先sleep 1000ms,所以可以看到"After lanuch a thread:"先输出,说明主线程异步执行,不受子线程影响。而"After get result "最后输出,说明get()方法会阻塞主线程,直到获取结果。

C++11 线程同步接口std::condition_variable和std::future的简单使用的更多相关文章

  1. 基于std::mutex std::lock_guard std::condition_variable 和std::async实现的简单同步队列

    C++多线程编程中通常会对共享的数据进行写保护,以防止多线程在对共享数据成员进行读写时造成资源争抢导致程序出现未定义的行为.通常的做法是在修改共享数据成员的时候进行加锁--mutex.在使用锁的时候通 ...

  2. APUE学习笔记——11 线程同步、互斥锁、自旋锁、条件变量

    线程同步     同属于一个进程的不同线程是共享内存的,因而在执行过程中需要考虑数据的一致性.     假设:进程有一变量i=0,线程A执行i++,线程B执行i++,那么最终i的取值是多少呢?似乎一定 ...

  3. 第30课 线程同步(std::condition_variable)

    一. 条件变量 (一)条件变量概述 多线程访问一个共享资源(或称临界区),不仅需要用互斥锁实现独享访问避免并发错误,在获得互斥锁进入临界区后,还需检查特定条件是否成立.当某个线程修改测试条件后,将通知 ...

  4. C++11并发——多线程条件变量std::condition_variable(四)

    https://www.jianshu.com/p/a31d4fb5594f https://blog.csdn.net/y396397735/article/details/81272752 htt ...

  5. C++11 并发指南五(std::condition_variable 详解)

    前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread,std::mut ...

  6. 转 C++11 并发指南std::condition_variable详解

    之前看过,但是一直没有怎么用就忘了,转一篇别人的文字记录下来 本文将介绍 C++11 标准中 <condition_variable> 头文件里面的类和相关函数. <conditio ...

  7. C++11 并发指南五(std::condition_variable 详解)(转)

    前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三(std::mutex 详解)>分别介绍了 std::thread,std::mut ...

  8. 【转】C++11 并发指南五(std::condition_variable 详解)

    http://www.cnblogs.com/haippy/p/3252041.html 前面三讲<C++11 并发指南二(std::thread 详解)>,<C++11 并发指南三 ...

  9. c++11 线程:让你的多线程任务更轻松

      介绍 本文旨在帮助有经验的Win32程序员来了解c++ 11线程库及同步对象 和 Win32线程及同步对象之间的区别和相似之处. 在Win32中,所有的同步对象句柄(HANDLE)是全局句柄.它们 ...

  10. c++11 线程池学习笔记 (一) 任务队列

    学习内容来自一下地址 http://www.cnblogs.com/qicosmos/p/4772486.html github https://github.com/qicosmos/cosmos ...

随机推荐

  1. git push origin master和git push的区别

    1.git push origin master 指定远程仓库名和分支名. 2.git push 不指定远程仓库名和分支名. 3. 这两者的区别:git push是git push origin ma ...

  2. [oeasy]python0015_键盘改造_将esc和capslock对调_hjkl_移动_双手正位

    键盘改造 回忆上次内容 上次练习了复制粘贴 按键 作用 <kbd>y</kbd><kbd>y</kbd> 复制光标行代码 到剪贴板 <kbd> ...

  3. oeasy教您玩转vim - 15 - # 行内查找

    行头行尾 回忆上节课内容 上次学了直接跳到开头和结尾 最重要的就是 ^.$ ^ 到开头 $ 到结尾 I 相当于^i A 相当于$a 查找帮助 还有什么呢? 还是继续在 motion 里面 ^ .$ 之 ...

  4. 第一章 FFmpeg初体验:在Centos7.9下编译FFmpeg!

    FFmpeg 官方网站:https://ffmpeg.org//download.html#build-linux 1.下载源码 1.1 第一种方式,官网上面下载源码包: 截至目前最新的版本是7.0. ...

  5. 【Vue】MineData 地图接入

    一.文档资料: MineData开放平台: https://minedata.cn/md-platform/login/login MineData V2.1.0 接口文档: http://113.1 ...

  6. 【Vue】Re12 Webpack 第三部分(插件、热部署、配置分离)

    一.HtmlWebpackPlugin webpack插件安装: npm install html-webpack-plugin --save-dev // 版本太高构建报错原因换这个 npm ins ...

  7. 【Layui】05 选项卡 Tabs

    文档位置: https://www.layui.com/doc/element/tab.html 案例演示: <div class="layui-tab"> <u ...

  8. 是忧是喜?——微软撑腰,奥特曼重回OpenAI任CEO —— 争论点:AI发展规范化是否会损害美国在AI领域的领先地位 —— AI发展是否需要规范化

    参考: https://mbd.baidu.com/newspage/data/landingsuper?context=%7B%22nid%22%3A%22news_1027953478745543 ...

  9. springboot中统一日志输出logback

    1.背景 为了便于分析和记录系统的运行,一个系统输出其运行的关键日志是非常必要的 比如输出:请求参数.请求url.请求方式.执行的sql.重要操作的日志.响应结果等 而这些日志中,大部分不需要我们手动 ...

  10. 旋转数组-python

    旋转数组 给定一个数组,将数组中的元素向右移动 k 个位置,其中 k 是非负数. 示例 1: 输入: [1,2,3,4,5,6,7] 和 k = 3 输出: [5,6,7,1,2,3,4] 解释: 向 ...