为啥 std::async 使用同一个线程运行函数
Posted
技术标签:
【中文标题】为啥 std::async 使用同一个线程运行函数【英文标题】:Why std::async runs functions with a same thread为什么 std::async 使用同一个线程运行函数 【发布时间】:2020-02-21 10:34:04 【问题描述】:我正在阅读一篇关于使用 c++ 进行并发编程的文章 (link)。在本文中,作者展示了 std::async 使用同一线程运行两个函数的代码。此外,当他将 std::future 与 std::async 一起使用时,它再次以不同的方式运行并使用独立线程运行所有函数。为什么 async 表现得像那样并且它具有这种不受控制的方式?另外,如何开发具有此功能的真正并发程序?这有可能吗,还是我应该错过它?
【问题讨论】:
【参考方案1】:我建议也阅读the reference,在“注释”部分中更好地解释发生了什么
如果从 std::async 获得的 std::future 没有从引用中移动或绑定到引用,则 std::future 的析构函数将在完整表达式的末尾阻塞 直到异步操作完成 [...]
或者换句话说,std::async
返回一个std::future
。一旦返回的对象被销毁,它将等到它所代表的运行操作结束。所以,如果你丢弃像
std::async(xyz);
返回值的析构函数在返回后立即被调用,因此等待xyz
完成。
如果你保持返回值喜欢
auto futureXyz = std::async(xyz);
它确实并行运行。那是因为返回值被移动到变量futureXyz
,所以局部变量“拥有”并行执行函数。
我不会称之为“不受控制的行为”,这只是你无法预料的事情,但它的定义很明确。
【讨论】:
但不能保证并行运行?它可能会异步运行,但出于并发的目的,这不一定有帮助? @TheGoldKnight23 我对此不是 100% 确定的。您可以指定一些标志来强制创建新线程,但默认情况下,实现将决定这一点。 与 std::thread 相比,它在控制并发方面的用处不大 只有在设置了std::launch::async时才会进行并行处理。 @SKCoderstd::launch::async
和 std::launch::deferred
都是默认设置的,所以实现决定发生什么。但是所有这些都可以在链接的参考资料中找到,我认为对于手头的问题并不重要。【参考方案2】:
来自 std::async 上的 cppreference 文档:
...异步运行函数 f (可能在单独的线程中...)(粗体是我的)。
std::async 确实不保证产生一个单独的线程来执行指令,如果你需要一个单独的线程来明确使用std::thread。这将保证生成一个单独的线程,您可以使用 std::future、原子变量等与它通信。
示例代码:
std::mutex cout_lock;
auto thread = std::thread([]
std::lock_guard<mutex> lock(cout_lock);
std::cout << "Hello world from thread!\n";
);
std::lock_guard<mutex> lock(cout_lock);
std::cout << "Hello world!\n";
thread.join();
注意我上面的代码是如何使用互斥锁的,因为 cout 本身并不是线程安全的
【讨论】:
以上是关于为啥 std::async 使用同一个线程运行函数的主要内容,如果未能解决你的问题,请参考以下文章