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. windows安装PHP的redis

    一定要先看vc版本和位 配置php的redis扩展 以php7.3 nts版为例,不同的php版本对应不通的redis扩展:下载扩展文件:https://windows.php.net/downloa ...

  2. [oeasy]python0074_修改字体背景颜色_background_color_背景色

    修改背景色 回忆上次内容 上次将asciiart和颜色一起来玩 7 种基本色 变化多端 不过到目前为止 改的 都是前景色 背景色可以修改吗? 重温参数 具体动手试试 print("\033[ ...

  3. oeasy教您玩转vim - 78 - # 操作系统文件格式 fileformat

    ​ 文件系统换行格式 fileformat 回忆保留环境的细节 上次我们了解了viminfo 他能够保存 命令行历史 标记 寄存器 把他和 :mksession 一起使用就可以完美复原环境了 还有什么 ...

  4. STM32开发环境配置记录——关于PlatformIO + VSCode + CubeMX的集成环境配置

    前言 ​ 为什么配置这样的一个环境呢?鄙人受够了Keil5那个简陋的工作环境了,实在是用不下去,调试上很容易跟CubeMX的代码产生不协调导致调试--发布代码不一致造成的一系列问题.CubeIDE虽说 ...

  5. 利用Elasticsearch实现地理位置、城市搜索服务

    最近用到一些简单的地理位置查询接口,基于当前定位获取用户所在位置信息(省市区),然后基于该信息查询当前区域的......提供服务. 然后就自己研究了下GIS,作为一个程序员.自己能不能实现这个功能呢? ...

  6. mybatisplus轻松完成一次模糊+分页查询

    之前一直用mybatis+pageinfo完成模糊+分页查询,还需要手写sql语句,之前一直没做尝试,今天试了试mybatisplus一个人完成模糊+分页,挺简单的 有一个小插曲是,我的前端接受的da ...

  7. Fiddler使用界面介绍-底部状态栏

    底部状态栏 1.Capturing抓包状态 Capturing:Fiddler正在抓包 空白:Fiddler停止抓包 2.All Processes抓取进程类型 All Processes:抓取所有进 ...

  8. 13、SpringMVC之异常解析器

    13.1.环境搭建 创建名为spring_mvc_exception的新module,过程参考9.1节和9.5节 13.1.1.创建错误提示页 <!DOCTYPE html> <ht ...

  9. 【MySQL】 线上补数据SQL

    昨天一下午就为了补业务数据,写SQL快崩溃了得... 直接贴不解释了 -- 先拿到[销售变更id]拿到[变更信息] -- 通过[变更信息]的主表id拿到[主表信息] -- 条件可以是 MAX(cc.i ...

  10. dll文件缺失

    下载[dll修复工具],花点钱就可以了,比自己百度香多了,网上的解决方案解决不了的这个一键全部解决,愿意百度的去百度,百度不到的建议使用,我吃过这个亏,电脑刷机丢失140.dll文件,网上百度一个都不 ...