async( std::launch policy, Function&& f, Args&&... args );
async( Function&& f, Args&&... args );
参数含义:
policy - 位掩码值,每个单独位控制允许的执行方法
- std::launch::async 启用异步求值
- std::launch::deferred 启用惰性求值
f - 要调用的可调用 (Callable) 对象
args... - 传递给 f 的参数
#include <iostream>
#include <vector>
#include <algorithm>
#include <numeric>
#include <future>
#include <string>
#include <mutex>
std::mutex m;
struct X {
void foo(int i, const std::string& str) {
//sleep(1);
/*
The sum is 10000
world!
43
53
Hello 42 // 最后也没执行完,被析构的时候打印
*/
std::lock_guard<std::mutex> lk(m);
std::cout << str << ' ' << i << '\n';
}
void bar(const std::string& str) {
std::lock_guard<std::mutex> lk(m);
std::cout << str << '\n';
}
int operator()(int i) {
std::lock_guard<std::mutex> lk(m);
std::cout << i << '\n';
return i + 10;
}
};
template <typename RandomIt>
int parallel_sum(RandomIt beg, RandomIt end)
{
auto len = end - beg;
if (len < 1000)
return std::accumulate(beg, end, 0);
RandomIt mid = beg + len/2;
auto handle = std::async(std::launch::async,
parallel_sum<RandomIt>, mid, end);
int sum = parallel_sum(beg, mid);
return sum + handle.get();
}
int main()
{
std::vector<int> v(10000, 1);
std::cout << "The sum is " << parallel_sum(v.begin(), v.end()) << '\n';
X x;
// 以默认策略调用 x.foo(42, "Hello") :
// 可能同时打印 "Hello 42" 或延迟执行
auto a1 = std::async(&X::foo, &x, 42, "Hello");
// 以 deferred 策略调用 x.bar("world!")
// 调用 a2.get() 或 a2.wait() 时打印 "world!"
auto a2 = std::async(std::launch::deferred, &X::bar, x, "world!");
// 以 async 策略调用 X()(43) :
// 同时打印 "43"
auto a3 = std::async(std::launch::async, X(), 43);
a2.wait(); // 打印 "world!" 等价于 a2.get()
std::cout << a3.get() << '\n'; // 打印 "53"
} // 若 a1 在此点未完成,则 a1 的析构函数在此打印 "Hello 42" (c++ 17及以上才行)
更换不同编译器打印结果可能为
The sum is 10000
world!
43
Hello 42
53
The sum is 10000
Hello 42
world!
43
53
async会返回一个future对象,当需要最终结果时,调用 std::future::get() 方法即可,该方法会阻塞线程直到期望值状态就绪为止。
future的析构函数和get()/wait()方法一样,也会阻塞
#include <iostream>
#include <future>
#include <chrono>
int main(){
auto sleep = [](int s) {
std::this_thread::sleep_for(std::chrono::seconds(s));
};
{
//std::async( std::launch::async, sleep, 5 ); // 临时对象被析构,阻塞 5s
//std::async( std::launch::async, sleep, 5 ); // 临时对象被析构,阻塞 5s,共花费10s
auto f1 = std::async( std::launch::async, sleep, 5 ); // 值传递给了临时对象,future可以马上析构,故两个同时析构只花费5s
auto f2 = std::async( std::launch::async, sleep, 5 );
}
}