在C++11中有个async异步函数,其声明如下:

template <class Fn, class... Args>
future<typename result_of<Fn(Args...)>::type>async (launch policy, Fn&& fn, Args&&... args);

该模板函数 async 异步地运行函数 fn 并返回最终将保存该函数调用结果的 std::future 中,其中policy策略有以下三种:

// 异步启动的策略
enum class launch {  // 异步启动,在调用std::async()时创建一个新的线程以异步调用函数,并返回future对象;async = 0x1,// 延迟启动,在调用std::async()时不创建线程,直到调用了future对象的get()或wait()方法时,才创建线程;                    deferred = 0x2,  // 自动,函数在某一时刻自动选择策略,这取决于系统和库的实现,通常是优化系统中当前并发的可用性           any = async | deferred,      sync = deferred
};
  • 参数 fn 是要调用的可调用 (Callable) 对象
  • 参数args 是传递给 f 的参数

异步调用函数可以大大提高程序运行的效率,验证如下:

辅助函数和声明

这个是验证程序的通用代码:

#include <iostream>           // std::cout
#include <thread>             // std::thread
#include <chrono>
#include <mutex>
#include <memory>
#include <functional>
#include <future>using namespace std;typedef std::chrono::steady_clock                STEADY_CLOCK;
typedef std::chrono::steady_clock::time_point    TIME_POINT;void print_diff_time(const TIME_POINT& t1, const TIME_POINT& t2)
{std::chrono::duration<double, std::milli> dTimeSpan = std::chrono::duration<double,std::milli>(t2-t1);std::cout << "time span : " << dTimeSpan.count() << "ms\n";
}

原始程序

下面演示的是,最原始的程序计算代码,关键代码如下:

//计算A函数
int calculateA()
{//延迟1msthis_thread::sleep_for(std::chrono::milliseconds(1));return 1;
}//计算B函数
int calculateB()
{//延迟2msthis_thread::sleep_for(std::chrono::milliseconds(2));return 2;
}//计算C函数
int calculateC()
{//延迟3msthis_thread::sleep_for(std::chrono::milliseconds(3));return 3;
}//统计三者的和
void test_common_time()
{TIME_POINT t1 = STEADY_CLOCK::now();int c = calculateA() + (calculateB() + calculateC());TIME_POINT t2 = STEADY_CLOCK::now();cout << "test_common_time result is :" <<  c << "  ";print_diff_time(t1, t2);
}

运行结果:

test_common_time result is :6  time span : 6.55506ms

多线程计算

没有引入多线程计算,程序计算时间达6.5ms,相对效率不高,下面演示多线程计算,代码如下:

//防止数据竞争
std::mutex g_mtu;void calA(int& sum)
{this_thread::sleep_for(std::chrono::milliseconds(1));//多线程加锁保护lock_guard<mutex> lk(g_mtu);sum += 1;
}void calB(int& sum)
{this_thread::sleep_for(std::chrono::milliseconds(2));lock_guard<mutex> lk(g_mtu);sum += 2;
}void calC(int& sum)
{this_thread::sleep_for(std::chrono::milliseconds(3));lock_guard<mutex> lk(g_mtu);sum += 3;
}//case2
void test_threads_time()
{int sum = 0;TIME_POINT t11 = STEADY_CLOCK::now();//启动三个线程,进行运算thread t1(calA, ref(sum));thread t2(calB, ref(sum)); thread t3(calC, ref(sum)); //等待计算完成t1.join();t2.join();t3.join();//计算完成TIME_POINT t22 = STEADY_CLOCK::now();cout << "test_threads_time result is :" <<  sum << "  ";print_diff_time(t11, t22);}

运行结果:

test_threads_time result is :6  time span : 3.57699ms

程序计算时间将近减少了一半,效率提高了很多,但是程序引入了锁机制,程序的实现相对复杂了。

异步调用

在C++11中引入了async异步调用函数,其封装了异步(多线程)实现的复杂过程,将计算结果保存在future<>中,通过get()获取每个对象的最终结果。代码如下:

//case3
void test_feture_time()
{int sum = 0;TIME_POINT t11 = STEADY_CLOCK::now();//异步调用future<int> f1 = std::async(calculateA);future<int> f2 = std::async(calculateB);future<int> f3 = std::async(calculateC);//get()函数会阻塞,直到结果返回sum = f1.get() + f2.get() + f3.get();TIME_POINT t22 = STEADY_CLOCK::now();cout << "test_feture_time result is :" <<  sum << "  ";print_diff_time(t11, t22);
}

运行结果:

test_future_time result is :6  time span : 3.76372ms

相比多线程版本的计算过程,async异步调用整个程序更加简洁,没有明显引入线程,锁,缓冲区等概念。又比如:

std::future<bool> asyncFuncCall = std::async(std::launch::async, func, args...);// 如果结果还未返回,那么就等待while(asyncFuncCall.wait_for(std::chrono::milliseconds(10)) != std::future_status::ready)
{// 做其它的事}

总结

async异步调用函数通过启动一个新线程或者复用一个它认为合适的已有线程,async是语义上的并发即可,并关心具体的调用策略。

”简单性”是async/future设计中最重视的一个方面;future一般也可以和线程一起使用,不过不要使用async()来启动类似I/O操作,操作互斥体(mutex),多任务交互操作等复杂任务。async()背后的理念和range-for statement很类似:简单事儿简单做,把复杂的事情留给一般的通用机制来搞定。

原文链接:https://blog.csdn.net/c_base_jin/article/details/79506347

C++11之std::async使用介绍相关推荐

  1. C++11中std::async的使用

    C++11中的std::async是个模板函数.std::async异步调用函数,在某个时候以Args作为参数(可变长参数)调用Fn,无需等待Fn执行完成就可返回,返回结果是个std::future对 ...

  2. 用C++11的std::async代替线程的创建

    转自:http://www.cnblogs.com/qicosmos/p/3534211.html c++11中增加了线程,使得我们可以非常方便的创建线程,它的基本用法是这样的: void f(int ...

  3. C++11多线程------std::async

    std::async可以认为是封装了一个std::promise,该函数返回一个std::future,用于获取其他线程的数据. 该函数的本质是内部封装构造了一个线程,然后传递给一个std::prom ...

  4. 概率论中指数分布介绍及C++11中std::exponential_distribution的使用

    指数分布:在深度学习中,我们经常会需要一个在x=0点处取得边界点(sharp point)的分布.为了实现这一目的,我们可以使用指数分布(exponential distribution): p(x; ...

  5. 概率论中高斯分布(正态分布)介绍及C++11中std::normal_distribution的使用

    高斯分布:最常用的分布是正态分布(normal distribution),也称为高斯分布(Gaussian distribution): 正态分布N(x;μ,σ2)呈现经典的"钟形曲线&q ...

  6. 概率论中伯努利分布(bernoulli distribution)介绍及C++11中std::bernoulli_distribution的使用

    Bernoulli分布(Bernoulli distribution):是单个二值随机变量的分布.它由单个参数ø∈[0,1],ø给出了随机变量等于1的概率.它具有如下的一些性质: P(x=1)= ø ...

  7. android ndk使用c 11,使用c 11 std :: async在android ndk中使用不完整类型无效

    我尝试使用以下函数来检查android ndk中是否支持std :: async以及windows中的cygwin.我使用的功能如下 机器:64位赢得8与cygwin Eclipse:Juno 4.2 ...

  8. C++11中std::packaged_task的使用

    C++11中的std::packaged_task是个模板类.std::packaged_task包装任何可调用目标(函数.lambda表达式.bind表达式.函数对象)以便它可以被异步调用.它的返回 ...

  9. C++11中std::shared_future的使用

    C++11中的std::shared_future是个模板类.与std::future类似,std::shared_future提供了一种访问异步操作结果的机制:不同于std::future,std: ...

最新文章

  1. ERICA:提升预训练语言模型实体与关系理解的统一框架
  2. Cent OS – Tomcat 7 - 集群
  3. JavaScript面向对象编程之Singleton类
  4. 蓝桥杯练习系统习题-算法训练3
  5. 已知图片大小,让其在页面中垂直水平居中
  6. 机器学习笔记I: 基于逻辑回归的分类预测
  7. 在Blazor中构建数据库应用程序——第5部分——查看组件——UI中的CRUD列表操作
  8. Prefuse 4未完
  9. Jmeter接口测试实战分享,你一定要知道的问题总结!
  10. 【opencv】左右两张图片实现全景拼接
  11. java 哈希表和向量_Java基础知识笔记(一:修饰词、向量、哈希表)
  12. 分析两个网页设计思路
  13. WebGL 3D on iOS8 正式版
  14. Boost Graph Library
  15. RN开发环境搭建-window
  16. 2019马哥python的百度网盘_马哥 2018 Python 全栈视频
  17. Code is far away from bug with the animal protecting
  18. PySide2学习总结(三)QtWidgets和QML
  19. Elastic Stack之Beats(Filebeat、Metricbeat)、Kibana、Logstash教程
  20. cad服务器手动改自动,手动挡改为自动挡,只需加装这“神器”老司机3000元就能...

热门文章

  1. 15岁杀人犯监狱学编程,37岁保释年薪70万
  2. 手把手教你研发属于自己的智能无人机
  3. android getwindow 在fragment不能使用,Android Fragment 布局使用 fitsSystemWindows = true 无效解决方案...
  4. pearsonr() python_十分钟搞懂“Python数据分析”
  5. jenkins pipeline php,Jenkins pipeline 系列二-为什么选择Pipeline
  6. python查找最长公共前缀_Python实现查找字符串数组最长公共前缀示例
  7. 浏览器打开出现证书错误_浏览器安全证书过期怎么办
  8. 大数据 -- zookeeper和kafka集群环境搭建
  9. JZOJ 2678. 树B
  10. Oracle日期转换为周,月,季度,半年,年