当前位置:网站首页>Item 36: Specify std::launch::async if asynchronicity is essential.
Item 36: Specify std::launch::async if asynchronicity is essential.
2022-08-01 00:32:00 【loongknown】
Item 36: Specify std::launch::async if asynchronicity is essential.
当你使用 std::async()
When executing a function or callable object,You usually expect this function to be executed asynchronously.但是, std::async()
Not necessarily as you wish.其实 std::async()
It is based on the execution strategy to decide whether to execute asynchronously. std::async()
There are two execution strategies,定义在 std::launch
作用域中:
std::launch::async
The function or executable object must execute asynchronously,That is, running on other threads.std::launch::deferred
The function or executable object is executed lazily.仅在std::async()
的返回对象std::future
调用get
或wait
时,It is executed synchronously in the current thread,And the caller blocks until the function execution completes.
std::async()
The default strategy is actually a combination of the two,That is, the following two have the same meaning:
auto fut1 = std::async(f); // run f using default launch policy
auto fut2 = std::async(std::launch::async | // run f either
std::launch::deferred, // async or
f); // deferred
under the default policy,f
It may be executed synchronously or asynchronously.正如 Item 35: Prefer task-based programming to thread-based. 中讨论的:The thread management module of the standard library is responsible for the creation and release of threads,Oversubscription can be effectively avoided、保证负载均衡.This is extremely convenient std::async
的使用.
但是,The default strategy also has the following problems:
- 无法预测
f
Whether to execute concurrently. - 无法预测
f
是否运行在get
或wait
on the thread at the time of the call. - Not even predictable
f
是否已经执行了.Because there is no guarantee that it will be calledget
或wait
.
当 f
To access thread-local storage(TLS,Thread Local Storage)时,It is impossible to predict which thread's local storage is being accessed.
auto fut = std::async(f); // TLS for f possibly for
// independent thread, but
// possibly for thread
// invoking get or wait on fut
std::async
The default policy of wait_for
Timeout call writing,可能导致 bug,例如:
using namespace std::literals; // for C++14 duration suffixes; see Item 34
void f() // f sleeps for 1 second, then returns
{
std::this_thread::sleep_for(1s);
}
auto fut = std::async(f); // run f asynchronously (conceptually)
while (fut.wait_for(100ms) != // loop until f has
std::future_status::ready) // finished running...
{
// which may never happen!
…
}
如果 std::async
是并发执行,That is, the execution strategy is std::launch::async
,以上代码没有问题.但是,如果执行策略为 std::launch::deferred
时,fut.wait_for
总是返回 future_status::deferred
,There is a problem with the above code.解决办法也很简单,先通过 wait_for
的超时时间为 0 来检测 std::async
是异步执行还是同步执行:
auto fut = std::async(f); // as above
if (fut.wait_for(0s) == // if task is
std::future_status::deferred) // deferred...
{
// ...use wait or get on fut
… // to call f synchronously
} else {
// task isn't deferred
while (fut.wait_for(100ms) != // infinite loop not
std::future_status::ready) {
// possible (assuming
// f finishes)
… // task is neither deferred nor ready,
// so do concurrent work until it's ready
}
… // fut is ready
}
综上,If your usage scenario is not the following,Then you need to consider whether you need to replace it std::async
的默认策略:
- 当调用
get
或wait
时,Tasks do not need to be executed concurrently. - It doesn't care which thread's local storage is being accessed.
- 可以保证
get
或wait
一定会被调用,Or it is acceptable for the task not to be executed. - 使用
wait_for
或wait_until
时,需要考虑std::launch::deferred
策略.
If not the above scenario,You may need to specify use std::launch::async
策略,That is, a thread is actually created to execute tasks concurrently:
auto fut = std::async(std::launch::async, f); // launch f asynchronously
This provides a wrapper for concurrently executing tasks:
template<typename F, typename... Ts> // C++11
inline
std::future<typename std::result_of<F(Ts...)>::type>
reallyAsync(F&& f, Ts&&... params) // return future
{
// for asynchronous
return std::async(std::launch::async, // call to f(params...)
std::forward<F>(f),
std::forward<Ts>(params)...);
}
reallyAsync
Accepts an executable object f
和 多个参数 params
,and perfectly forwarded to std::async
,同时使用 std::launch::async
策略.C++14 版本如下:
template<typename F, typename... Ts>
inline
auto // C++14
reallyAsync(F&& f, Ts&&... params)
{
return std::async(std::launch::async,
std::forward<F>(f),
std::forward<Ts>(params)...);
}
至此,本文结束.
参考:
边栏推荐
- WeChat applet page syntax
- 南方科技大学:Xiaoying Tang | AADG:视网膜图像分割领域泛化的自动增强
- Named Entity Recognition - Model: BERT-MRC
- Nmap 操作手册 - 完整版
- JVM面试题总结(持续更新中)
- Nmap Operation Manual - Full Version
- 2022年最新重庆建筑八大员(电气施工员)模拟题库及答案
- 面试题:实现死锁
- Binary tree traversal non-recursive program -- using stack to simulate system stack
- 自动化机器学习pycaret: PyCaret Basic Auto Classification LightGBM
猜你喜欢
ECCV2022 Workshop | 复杂环境中的多目标跟踪和分割
Team of Professor Chen Jianyu of Tsinghua University | Contact Safety Reinforcement Learning Framework Based on Contact-rich Robot Operation
Kyoto University:Masaki Waga | 黑箱环境中强化学习的动态屏蔽
如何编辑epub电子书的目录
类和对象:中
Application of integrated stepper motor in UAV automatic airport
ROS2系列知识(4): 理解【服务】的概念
虹科分享|如何用移动目标防御技术防范未知因素
两院院士直言:不要迷信院士
一行代码解决CoreData托管对象属性变更在SwiftUI中无动画效果的问题
随机推荐
Classes and Objects: Medium
MYSQL查询截取优化分析
C字符串数组反转
Introduction to the five data types of Redis
VPGNet
[AMEX] LGBM Optuna美国运通信用卡欺诈赛 kaggle
Notes on how to use zeno
The role of /etc/resolv.conf
[MATLAB project combat] LDPC-BP channel coding
TFC CTF 2022 WEB Diamand WriteUp
Redis五种数据类型简介
声称AI存在意识,谷歌工程师遭解雇:违反保密协议
NIO programming
STK8321 I2C(昇佳-加速度传感器)示例
网关gateway跨域
RTL8762DK WDG(六)
C# Rectangle basic usage and picture cutting
MYSQL逻辑架构
lua入门案例实战123DIY
Basic use of vim - bottom line mode