如何确定std::async的任务何时开始?

How to make sure when task of std::async starts?

提问人:f1msch 提问时间:7/11/2023 更新时间:7/11/2023 访问量:75

问:

我正在阅读 cppreference async#Notes 正如它所说,我真的不明白它是什么意思。但作为结论,我知道这并不总是立即启动一个以异步方式运行的新线程。Notesstd::async(std::launch::async, ...)

在 cppreference 的示例中,似乎在同一个线程中运行并追求?是吗?f()g()g()f()

如果

void ff(){std::async(std::launch::async, []{ f(); });}
void gg(){std::async(std::launch::async, []{ g(); });}
int main(){
    ff();
    gg();
}

会不等完成就开始了吗?g()f()

总而言之,如何理解 async#Notes 所讲述的内容?可以告诉我更多细节或例子吗?

C++ 异步

评论

1赞 Raffallo 7/11/2023
is not always starting a new thread immediatelly which runs as async.它正在运行,但第一个正在返回 ,在析构函数中,它将锁定主线程,直到第一个操作不会结束他的工作。std::asyncstd::future
1赞 Sam Varshavchik 7/11/2023
“seem running in the same thread” 是什么意思?
0赞 Pete Becker 7/11/2023
要回答标题中的问题,(注意:不需要 lambda)将阻塞,直到调用完成。这是因为该调用忽略了调用返回的对象;返回对象的析构函数将立即调用,并且该析构函数会阻塞,直到完成。因此,在代码转到下一个语句之前,任务已启动并完成。std::async(f));f()std::futureasyncf()

答:

5赞 463035818_is_not_an_ai 7/11/2023 #1

作为参考,来自 cppreference(强调我的):

通过在默认启动策略中启用其他(实现定义的)位,实现可以扩展第一个重载的行为。std::async

实现定义的启动策略的示例包括同步策略(在调用中立即执行)和任务策略(类似于 ,但不会清除线程局部变量)std::asyncstd::async

如果从 获取的引用未从引用中移动或绑定到引用,则 will 的析构函数将阻塞在完整表达式的末尾,直到异步操作完成,实质上使代码(如以下代码)同步:std::futurestd::asyncstd::future

std::async(std::launch::async, []{ f(); }); // temporary's dtor waits for f()
std::async(std::launch::async, []{ g(); }); // does not start until f() completes

请注意,析构函数是通过调用永不阻塞以外的方式获得的。std::futuresstd::async

注释主要指出,从调用返回到阻塞,直到任务完成。关于评估顺序,上面的代码或多或少等同于std::futurestd::async

 f();
 g();

是否在相同线程或不同线程上调用 和 取决于实现。如果你想要真正的异步性,你必须保留返回的 future:fg

 auto f1 = std::async(std::launch::async, []{ f(); });
 auto f2 = std::async(std::launch::async, []{ g(); });

只有这样,您才会获得异步调用,并首先调用 OR 或。它们是否在同一线程上被调用仍然取决于实现。gf

他们没有在任何地方这么说,并且必须在同一线程上调用,得出这样的结论是错误的。可以在没有并发和异步调用的情况下编写多线程代码。通常这不是您想要的,因此注释指出了返回的重要性。fgstd::future