文章目录

  • 一、std::future与std::async
    • 1.基本概念
    • 2.代码演示
  • 二、std::future与std::packaged_task
    • 1.基本知识
    • 2.代码演示
  • 三、std::future与std::promise
    • 1.基本知识
    • 2.代码演示

一、std::future与std::async

1.基本概念

(1)std::future的基本知识
std::future期待一个返回,从一个异步调用的角度来说,future更像是执行函数的返回值,C++标准库使用std::future为一次性事件建模,如果一个事件需要等待特定的一次性事件,那么这线程可以获取一个future对象来代表这个事件。
异步调用往往不知道何时返回,但是如果异步调用的过程需要同步,或者说后一个异步调用需要使用前一个异步调用的结果。这个时候就要用到future。
线程可以周期性的在这个future上等待一小段时间,检查future是否已经ready,如果没有,该线程可以先去做另一个任务,一旦future就绪,该future就无法复位(无法再次使用这个future等待这个事件),所以future代表的是一次性事件

(2)std::future的类型
在库的头文件中声明了两种future,唯一future(std::future)和共享future(std::shared_future)这两个是参照std::unique_ptr和std::shared_ptr设立的,前者的实例是仅有的一个指向其关联事件的实例,而后者可以有多个实例指向同一个关联事件,当事件就绪时,所有指向同一事件的std::shared_future实例会变成就绪。
std::future是一个模板,例如std::future,模板参数就是期待返回的类型,虽然future被用于线程间通信,但其本身却并不提供同步访问,热门必须通过互斥元或其他同步机制来保护访问。

(1)std::future的使用时机
future使用的时机是当你不需要立刻得到一个结果的时候,你可以开启一个线程帮你去做一项任务,并期待这个任务的返回,但是std::thread并没有提供这样的机制,这就需要用到std::async和std::future(都在头文件#include < future >中声明)std::async返回一个std::future对象,而不是给你一个确定的值(所以当你不需要立刻使用此值的时候才需要用到这个机制)。当你需要使用这个值的时候,对future使用get(),线程就会阻塞直到future就绪,然后返回该值。

2.代码演示

代码1:未使用std::future

#include<iostream>
#include<future>int add(int a, int b) {std::this_thread::sleep_for(std::chrono::seconds(5));//休眠五秒return a + b;
}void fun() {std::cout << "this is fun()" << std::endl;
}int main()
{int c = add(1,2);//这行代码执行需要5秒,5秒后再向下执行fun();std::cout << c << std::endl;return 0;
}


代码2:使用future

#include<iostream>
#include<future>int add(int a, int b) {std::this_thread::sleep_for(std::chrono::seconds(5));//休眠五秒return a + b;
}void fun() {std::cout << "this is fun()" << std::endl;
}int main() {std::future<decltype(add(1, 2))> result = std::async(add, 1, 2);//auto result = std::async(add, 1, 2); //OK 可以使用占位符auto进行类型推导//std::future<int> result = std::async(add, 1, 2);//OK  由于知道函数的返回类型 所以可以直接确定模板类型int//std::future<decltype(add, int, int)>result = std::async(add, 1, 2);//errorfun();std::this_thread::sleep_for(std::chrono::seconds(5));//休眠5秒std::cout << result.get() << std::endl;return 0;
}


跟thread类似,async允许你通过将额外的参数添加到调用中,来将附加参数传递给函数。如果传入的函数指针是某个类的成员函数,则还需要将类对象指针传入(直接传入,传入指针,或者是std::ref封装)。
默认情况下,std::async是否启动一个新线程,或者在等待future时,任务是否同步运行都取决于你给的参数。这个参数为std::launch类型std::launch::defered表明该函数会被延迟调用,直到在future上调用get()或者wait()为止std::launch::async,表明函数会在自己创建的线程上运行

二、std::future与std::packaged_task

1.基本知识

如果说std::async和std::future还是分开看的关系的话,那么std::packaged_task就是将任务和future绑定在一起的模板,是一种封装对任务的封装。
可以通过std::packaged_task对象获取任务相关联的future,调用get_future()方法可以获得std::packaged_task对象绑定的函数的返回值类型的future。std::packaged_task的模板参数是函数签名
例如int add(int a, intb)的函数签名就是int(int, int)

2.代码演示

由于和第一大点的差不多,这里简单代码演示

#include<iostream>
#include<future>int add(int a, int b) {std::this_thread::sleep_for(std::chrono::seconds(5));//休眠五秒return a + b;
}void fun() {std::cout << "this is fun()" << std::endl;
}int main() {std::packaged_task<int(int, int)>task(add);//将函数和task绑定在一起了std::future<int> result = task.get_future();fun();task(1, 2);//相当于执行函数 必须执行 否则的话 result.get()会一直阻塞 当我们执行这个task(1,2)的时候才算开始执行add函数 换句话说,当我们执行task(1,2)的时候,才会执行add函数里的5秒休眠std::cout << result.get() << std::endl;return 0;
}

三、std::future与std::promise

1.基本知识

从字面意思上理解promise代表一个承诺。promise比std::packaged_task抽象层次低。
std::promise提供了一种设置值的方式,它可以在这之后通过相关联的std::future对象进行读取。换种说法,之前已经说过std::future可以读取一个异步函数的返回值了,那么这个std::promise就提供一种方式手动让future就绪。

2.代码演示

#include <future>
#include <string>
#include <thread>
#include <iostream>
using namespace std;
void print(std::promise<std::string>& p)
{this_thread::sleep_for(chrono::seconds(5));p.set_value("There is the result whitch you want.");
}
void do_some_other_things()
{std::cout << "Hello World" << std::endl;
}
int main()
{std::promise<std::string> promise;std::future<std::string> result = promise.get_future();//thread的时候传入引用必须使用std::ref()函数std::thread t(print, std::ref(promise));//开始执行print函数 do_some_other_things();//打印“hellowworld”this_thread::sleep_for(chrono::seconds(5));std::cout << result.get() << std::endl;//什么时候想要线程的返回值什么时候result.get()t.join();return 0;
}

C++——异步操作(std::future、std::async、std::packaged_task、std::promise)相关推荐

  1. C++ 中 async、packaged_task、promise 区别及使用

    Introduction 编程难,多线程编程更难 – 鲁迅 多线程编程,如此令人着迷.令人痛恨的字眼.人类为了追求更好的效率.更快的速度,非常残忍的发明了多线程编程,这不仅让写代码的难度陡增,同时也加 ...

  2. C++多线程std::async、std::future、std::packaged_task、std::promise

    std::async std::async用于创建异步任务,实际上就是创建一个线程执行相应任务,默认立即开始执行. std::async就是异步编程的高级封装,std::async的操作,其实相当于封 ...

  3. std::future和std::promise和std::packaged_task

    std::future 其实future有两个兄弟,一个是std::future, 一个是它大哥std::shared_future.他们的区别就是std::future只支持移动语义,它所引用的共享 ...

  4. C++ 并发指南<future>(2)std::packaged_task

    std::packaged_task 包装一个可调用的对象,并且允许异步获取该可调用对象产生的结果,从包装可调用对象意义上来讲,std::packaged_task 与 std::function 类 ...

  5. C++11中std::future的使用

    C++11中的std::future是一个模板类.std::future提供了一种用于访问异步操作结果的机制.std::future所引用的共享状态不能与任何其它异步返回的对象共享(与std::sha ...

  6. C++11之std::future对象使用说明

    std::future介绍 在前面几篇文章中基本都用到thread对象,它是C++11中提供异步创建多线程的工具.但是我们想要从线程中返回异步任务结果,一般需要依靠全局变量:从安全角度看,有些不妥:为 ...

  7. C++11 并发指南四(future 详解三 std::future std::shared_future)

    上一讲<C++11 并发指南四(<future> 详解二 std::packaged_task 介绍)>主要介绍了 <future> 头文件中的 std::pack ...

  8. C++ 并发指南< future >(3)std::future std::shared_future

    std::future介绍 简单地说,std::future 可以用来获取异步任务的结果,因此可以把它当成一种简单的线程间同步的手段. std::future 通常由某个 Provider 创建,你可 ...

  9. C++ 的 std::promise 和 std::future

    介绍 编写多线程应用时,无法避免的要进行线程间数据同步/通信.std::promise 和 std::future 是 C++ 进行单向数据传递的一种方式.std::promise 是数据的输入端,s ...

  10. C++ 多线程:std::future

    概念 我们前面介绍的std::thread 是C++11中提供异步创建多线程的工具,只能是异步运行任务,却无法获取任务执行的结果,一般都是依靠全局对象,全局对象在多线程下是及其不安全的,为此标准库提供 ...

最新文章

  1. 微型计算机步进电机控制,步进电机的微型计算机控制
  2. FSMO角色的Windows界面查看和转移示例
  3. 分治算法-02凸包问题
  4. 执行完execute和update后存储过程变成invalid_学会反射后,我被面试官录取了(干货)
  5. 第44课 角谷猜想 动动脑 第3题 完善程序
  6. python 拟牛顿法 求非线性方程_C语言实现迭代法求非线性方程的根
  7. pytest-xdist分布式执行测试用例
  8. 哪款浏览器好用_超级实用!让你效率倍增的6款浏览器插件
  9. Linux常用基本命令:三剑客命令之-awk内置函数用法
  10. 对计算机病毒防治最科学的方法是什么,常见的计算机病毒防治措施有什么
  11. 主动降噪(ANC),让你静心聆听声音
  12. openwrt官方固件怎么中继网络
  13. 产品静电ESD测试标准
  14. 十三、注解(高琪java300集+java从入门到精通笔记)
  15. C++---常见秋招、春招问题汇总(持续更新)
  16. 大长今人物系列:长今的心理课——医女张德(转载)
  17. 本地——云服务器文件传输
  18. 如何制作一寸、二寸、六寸照片。以后不用再去照相馆
  19. Python中的break语句
  20. RedisTemplate报错WRONGTYPE Operation against a key holding the wrong kind of value

热门文章

  1. nginx.conf文件配置后访问边下载 以及yaf框架使用中NGINX.conf文件配置
  2. 牛客网(剑指offer) 第十九题 顺时针打印矩阵
  3. c语言 读取 文件大小,c – ifstream :: ifstream可以读取的最大文件大小是多少
  4. LeetCode Algorithm 面试题 16.10. 生存人数
  5. 350. Intersection of Two Arrays II 两个数组的交集 II
  6. 数据库开发——MySQL——primary key
  7. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1103:陶陶摘苹果
  8. 信息学奥赛一本通(C++)在线评测系统——基础(一)C++语言——1072:鸡尾酒疗法
  9. The SetStack Computer
  10. 【Linux网络编程】广播