C++ 参考手册
- C++11
- C++14
- C++17
- C++20
- C++ 编译器支持情况表
- 独立与宿主实现
- C++ 语言
- C++ 关键词
- 预处理器
- C++ 标准库头文件
- 具名要求
- 功能特性测试 (C++20)
- 工具库
- 类型支持(基本类型、RTTI、类型特性)
- 概念库 (C++20)
- 错误处理
- 动态内存管理
- 日期和时间工具
- 字符串库
- 容器库
- 迭代器库
- 范围库 (C++20)
- 算法库
- 数值库
- 输入/输出库
- 文件系统库
- 本地化库
- 正则表达式库
- 原子操作库
- 线程支持库
- std::thread
- std::stop_token
- std::stop_source
- std::stop_callback
- std::this_thread::get_id
- std::shared_timed_mutex
- std::shared_lock
- std::lock_guard
- std::hardware_destructive_interference_size, std::hardware_constructive_interference_size
- std::counting_semaphore, std::binary_semaphore
- std::jthread
- cpp/thread/barrier
- std::future
- std::this_thread::yield
- std::this_thread::sleep_for
- std::this_thread::sleep_until
- std::mutex
- std::recursive_mutex
- std::shared_mutex
- std::timed_mutex
- std::recursive_timed_mutex
- std::scoped_lock
- std::unique_lock
- std::defer_lock_t, std::try_to_lock_t, std::adopt_lock_t
- std::lock
- std::try_lock
- std::defer_lock, std::try_to_lock, std::adopt_lock
- std::once_flag
- std::call_once
- std::condition_variable
- std::condition_variable_any
- std::notify_all_at_thread_exit
- std::cv_status
- std::latch
- std::promise
- std::shared_future
- std::packaged_task
- std::async
- std::launch
- std::future_status
- std::future_error
- std::future_category
- std::future_errc
- 注释
- 实验性 C++ 特性
- 有用的资源
- 索引
- std 符号索引
- 协程支持 (C++20)
- C++ 关键词
std::async
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
(C++17 前)
std::future<std::invoke_result_t<std::decay_t<Function>,
std::decay_t<Args>...>>
(C++20 前)
[[nodiscard]]
std::future<std::invoke_result_t<std::decay_t<Function>,
std::decay_t<Args>...>>
std::future<std::result_of_t<std::decay_t<Function>(std::decay_t<Args>...)>>
(C++17 前)
std::future<std::invoke_result_t<std::decay_t<Function>,
std::decay_t<Args>...>>
(C++20 前)
[[nodiscard]]
std::future<std::invoke_result_t<std::decay_t<Function>,
std::decay_t<Args>...>>
函数模板 async
异步地运行函数 f
(潜在地在可能是线程池一部分的分离线程中),并返回最终将保有该函数调用结果的 std::future 。
f
可能执行于另一线程,或者它可能在查询产生的 std::future 的值时同步运行。policy
,以参数 args
调用函数 f
:
- 若设置 async 标志(即 (policy & std::launch::async) != 0 ),则
async
在新的执行线程(初始化所有线程局域对象后)执行可调用对象f
,如同产出 std::thread(std::forward<F>(f), std::forward<Args>(args)...) ,除了若f
返回值或抛出异常,则于可通过async
返回给调用方的 std::future 访问的共享状态存储结果。 - 若设置 deferred 标志(即 (policy & std::launch::deferred) != 0 ),则
async
以同 std::thread 构造函数的方式转换f
与args...
,但不产出新的执行线程。而是进行惰性求值:在async
所返回的 std::future 上首次调用非定时等待函数,将导致在当前线程(不必是最初调用std::async
的线程)中,以args...
(作为右值传递)的副本调用f
(亦作为右值)的副本。将结果或异常置于关联到该 future 的共享状态,然后才令它就绪。对同一 std::future 的所有后续访问都会立即返回结果。 - 若
policy
中设置了 std::launch::async 和 std::launch::deferred 两个标志,则进行异步执行还是惰性求值取决于实现。
- 若设置 async 标志(即 (policy & std::launch::async) != 0 ),则
|
(C++14 起) |
任何情况下,对 std::async
的调用同步于(定义于 std::memory_order )对 f
的调用,且 f
的完成先序于令共享状态就绪。若选择 async
策略,则关联线程的完成同步于首个等待于共享状态上的函数的成功返回,或最后一个释放共享状态的函数的返回,两者的先到来者。
参数
f | - | 要调用的可调用 (Callable) 对象 | ||||||||
args... | - | 传递给 f 的参数
| ||||||||
policy | - | 位掩码值,每个单独位控制允许的执行方法
| ||||||||
类型要求 | ||||||||||
-Function, Args 必须满足可移动构造 (MoveConstructible) 的要求。
|
返回值
指代此次调用 std::async
所创建的共享状态的 std::future 。
异常
若运行策略等于 std::launch::async 且实现无法开始新线程(该情况下,若运行策略为 async|deferred
或设置了额外位,则它将回退到 deferred 或实现定义的策略),则抛出以 std::errc::resource_unavailable_try_again 为错误条件的 std::system_error ,或者若无法分配内部数据结构所用的内存,则为 std::bad_alloc 。
注解
实现可以通过在默认运行策略中启用额外(实现定义的)位,扩展 std::async 第一重载的行为。
实现定义的运行策略的例子是同步策略(在 async 调用内立即执行)和任务策略(类似 async ,但不清理线程局域对象)。
若从 std::async
获得的 std::future
未被移动或绑定到引用,则在完整表达式结尾, std::future 的析构函数将阻塞直至异步计算完成,实质上令如下代码同步:
std::async(std::launch::async, []{ f(); }); // 临时量的析构函数等待 f() std::async(std::launch::async, []{ g(); }); // f() 完成前不开始
(注意,以调用 std::async 以外的方式获得的 std::future 的析构函数决不阻塞)
示例
#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) { 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!" std::cout << a3.get() << '\n'; // 打印 "53" } // 若 a1 在此点未完成,则 a1 的析构函数在此打印 "Hello 42"
可能的输出:
The sum is 10000 43 world! 53 Hello 42
缺陷报告
下列更改行为的缺陷报告追溯地应用于以前出版的 C++ 标准。
DR | 应用于 | 出版时的行为 | 正确行为 |
---|---|---|---|
LWG 2021 | C++11 | 返回类型不正确, deferred 的情况下参数的值类别不明 | 更正返回类型,明确使用右值 |