什么是std::async?
std::async 是一个接受回调(函数对象or函数本体)作为参数的函数模板,可以同步或异步执行
std::async特点分析
std::async 定位于头文件
template< class Function, class... Args >
std::future<std::invoke_result_t<std::decay_t<Function>, std::decay_t<Args>...>>
async( std::launch policy, Function&& fn, Args&&... args );
函数模板 async 异步地运行函数 fn,最终返回保有该函数调用结果的std::future。
- std::launch policy它控制std::async的异步行为,我们可以用三种不同的启动策略来创建std::async;
- std::launch::async 传递的可调用对象异步执行;
- std::launch::deferred 传递的可调用对象同步执行;
- std::launch::async | std::launch::deferred 可以异步或是同步,取决于操作系统,我们无法控制;
- 如果未指定,默认运行策略使用std::launch::async | std::launch::deferred,异步运行或不运行,这取决于系统的负载,但我们无法控制它;
- fn:函数,函数对象、lambda等;
- args 函数fn的调用参数;
代码释义
#include <iostream>
#include <string>
#include <chrono>
#include <thread>
#include <future>
using namespace std;
int AddFunc(int a, int b, int sleep)
{
cout << "function thread id=" << std::this_thread::get_id() << endl;
cout << __FUNCTION__ << " sleep begin " << std::this_thread::get_id() << endl;
this_thread::sleep_for(chrono::seconds(sleep));
cout << __FUNCTION__ << " sleep end " << std::this_thread::get_id() << endl;
auto ret = a + b;
cout << "thread id=" << std::this_thread::get_id() << " ret = " << ret << endl;
return ret;
}
void TestBindRetFuture()
{
{
//当async返回值无绑定的future,直到执行完毕才开始新的async
async(launch::async, AddFunc, 1, 2, 5);
async(launch::async, AddFunc, 3, 4, 2);
cout << "==========================================================" << endl;
}
{
//绑定返回值,则多个async同时异步执行
auto ret_future1 = async(launch::async, AddFunc, 1, 2, 5);
auto ret_future2 = async(launch::async, AddFunc, 3, 4, 2);
cout << "==========================================================" << endl;
}
}
void TestLaunchPolicy()
{
{
//异步函数
future<int> ret_future1 = async(launch::async, AddFunc, 1, 2, 2);
cout << "main create async async" << endl;
this_thread::sleep_for(chrono::seconds(1));
cout << "main sleep_for end" << endl;
int ret = ret_future1.get();
cout << "async ret_future1=" << ret << endl;
cout << "==========================================================" << endl;
}
{
//同步函数,函数会在future.get()时才执行
future<int> ret_future1 = async(launch::deferred, AddFunc, 1, 2, 2);
cout << "main create async deferred" << endl;
this_thread::sleep_for(chrono::seconds(1));
cout << "main sleep_for end" << endl;
int ret = ret_future1.get();
cout << "deferred ret_future1=" << ret << endl;
cout << "==========================================================" << endl;
}
}
void TestClassFunc()
{
class TmpClass {
public:
TmpClass(){};
~TmpClass(){};
int RetFuncAdd(int a, int b, int sleep = 0)
{
cout << "RetFuncAdd thread id=" << std::this_thread::get_id() << endl;
cout << __FUNCTION__ << " sleep begin " << std::this_thread::get_id() << endl;
this_thread::sleep_for(chrono::seconds(sleep));
cout << __FUNCTION__ << " sleep end " << std::this_thread::get_id() << endl;
obj_ret = a + b;
cout << "thread id=" << std::this_thread::get_id() << " ret = " << obj_ret << endl;
return obj_ret;
}
int GetObjRet() { return obj_ret; };
private:
int obj_ret;
};
TmpClass test_obj;
//异步函数
future<int> ret_future1 = async(launch::async, &TmpClass::RetFuncAdd, &test_obj, 1, 2, 2);
cout << "main create async async" << endl;
this_thread::sleep_for(chrono::seconds(1));
cout << "main sleep_for end" << endl;
int ret = ret_future1.get();
cout << "async ret_future1=" << ret << endl;
cout << "TmpClass obj_ret=" << test_obj.GetObjRet() << endl;
cout << "==========================================================" << endl;
}
int main()
{
cout << "main thread id=" << std::this_thread::get_id() << endl;
//TestBindRetFuture();
//TestLaunchPolicy();
TestClassFunc();
return 0;
}
std::async注意点
若从 std::async 获得的 std::future 未被移动或绑定到引用,则在完整表达式的末尾, std::future 的析构函数将阻塞直至异步计算完成,简化代码释义如下:
std::async(std::launch::async, []{ func1(); }); // 临时量的析构函数等待 func1(),返回值未绑定
std::async(std::launch::async, []{ func2(); }); // func1() 完成前不开始