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. ArkTS基础知识

    [习题]ArkTS基础知识 及格分85/ 满分100   判断题 1. 循环渲染ForEach可以从数据源中迭代获取数据,并为每个数组项创建相应的组件. 正确(True)错误(False) 回答正确 ...

  2. odoo Actions学习总结

    环境 odoo-14.0.post20221212.tar Actions(动作) action定义系统响应用户操作的行为:登录.操作按钮.选择发票等- action可以存储在数据库中,也可以作为字典 ...

  3. 怎么使用github action定时运行js脚本?

    github action是使用yaml文件来做到CI/CD的,文件位置存放在 .github/workflows,yaml文件内容如下: name: ncatest.cx.js on: push: ...

  4. Jmeter函数助手1-CSVRead

    CSVRead函数适用于读取文件获取参数值. 用于获取值的CSV文件 | *别名:csv文件路径 CSV文件列号| next| *alias:读取列,0表示第一列,1表示第二列 1.首先我们需要一个文 ...

  5. ComfyUI插件:ComfyUI layer style 节点(二)

    前言: 学习ComfyUI是一场持久战,而ComfyUI layer style 是一组专为图片设计制作且集成了Photoshop功能的强大节点.该节点几乎将PhotoShop的全部功能迁移到Comf ...

  6. 循环神经网络 —— LSTM 有状态模型(stateful LSTM)和无状态模型(stateless LSTM)

    相关参考: 训练后的LSTM模型在进行预测时的初始h_n和c_n是什么或应该怎么设置? Keras中对RNN网络的statefull和stateless设置: 链接:https://keras.io/ ...

  7. 【运维技巧】海豚调度工作流实例卡在正在停止&任务实例卡在正在运行怎么办?

    在大数据调度系统中,,大家可能会碰到任务实例状态更新不及时的情况. 对于Apache DolphinScheduler用户来说,这可能意味着前端显示的任务状态与实际情况不一致,即使任务已经在后台停止运 ...

  8. python调用第三方java包实例

    先看结果: 对于python与java的互调,我一开始是用的py4j,但是后来发现在使用方法的时候,不知道如何在python中导入jar包,然后网上的资料也比较少.后来想不出来办法,又看到有Jpype ...

  9. RabbitMq高级特性之消费端限流 通俗易懂 超详细 【内含案例】

    RabbitMq高级特性之消费端限流 介绍 消息队列中囤积了大量的消息, 或者某些时刻生产的消息远远大于消费者处理能力的时候, 这个时候如果消费者一次取出大量的消息, 但是客户端又无法处理, 就会出现 ...

  10. 瑞芯微|如何让拥有双网口的Linux设备实现数据包转发?【超实用】

    本文主要讲解如何,解决基于3568实现双网口互通问题. 一.组网 如下图所示: rk3568自带2个千兆以太口,对应网卡名称为:eth0.eth1 pc1和pc2分别连接这2个网口 pc1与eth0连 ...