查看原文
其他

async的两个坑

程序喵 程序喵大人 2022-08-22

一般人可能都知道C++异步操作有async这个东西。但不知道大家是否注意过,其实它有两个坑:

  1. 它不一定真的会异步执行

  2. 它有可能会阻塞


下面是async具体的介绍:


async是比future,packaged_task,promise更高级的东西,它是基于任务的异步操作。

通过async可以直接创建异步的任务,返回的结果会保存在future中,不需要像packaged_task和promise那么麻烦。

关于线程操作可以优先使用async,看一段使用代码:

#include <functional>#include <future>#include <iostream>#include <thread>
using namespace std;
int func(int in) { return in + 1; }
int main() { auto res = std::async(func, 5); // res.wait(); cout << res.get() << endl; // 阻塞直到函数返回 return 0;}

使用async异步执行函数是不是方便多啦。


async具体语法如下:

async(std::launch::async | std::launch::deferred, func, args...);


第一个参数是创建策略:

  • std::launch::async表示任务执行在另一线程

  • std::launch::deferred表示延迟执行任务,调用get或者wait时才会执行,不会创建线程,惰性执行在当前线程。

如果不明确指定创建策略,以上两个都不是async的默认策略,而是undefined,它是一个基于任务的程序设计,内部有一个调度器(线程池),会根据实际情况决定采用哪种策略。


若从 std::async 获得的 std::future 未被移动或绑定到引用,则在完整表达式结尾。


注意:std::future的析构函数将阻塞直至异步计算完成,实际上相当于同步操作:

std::async(std::launch::async, []{ f(); }); // 临时量的析构函数等待 f()std::async(std::launch::async, []{ g(); }); // f() 完成前不开始

注意:关于async启动策略这里网上和各种书籍介绍的五花八门,这里会以cppreference为主。


有时候我们如果想真正执行异步操作可以对async进行封装,强制使用std::launch::async策略来调用async。

template <typename F, typename... Args>inline auto ReallyAsync(F&& f, Args&&... params) { return std::async(std::launch::async, std::forward<F>(f), std::forward<Args>(params)...);}


参考资料

https://en.cppreference.com/w/cpp/thread/async


打完收工。



往期推荐



C++都有哪些就业方向?是否应该学习C++?

如何优雅的实现多维数组

推荐学习这个开源项目

高端操作:不用继承我也能实现多态

手撸一个智能指针

知乎高赞:为什么有些大公司技术弱爆了?

冷门知识点:进程间通信如何加锁?

不要再无脑背诵面向对象三大特性了

继承和组合,究竟我要选哪个?

有没有比友元更优雅的方式

一位大佬对于 Qt 学习的最全总结(三万字干货)


您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存