当未存储返回值时,std::async 不会产生新线程

Posted

技术标签:

【中文标题】当未存储返回值时,std::async 不会产生新线程【英文标题】:std::async won't spawn a new thread when return value is not stored 【发布时间】:2012-02-28 21:59:07 【问题描述】:

考虑一下我有 Lamba foo,它只是做一些事情,不需要返回任何东西。 当我这样做时:

std::future<T> handle = std::async(std::launch::async, foo, arg1, arg2);

一切运行良好,lamba 将在新线程中生成。 但是,当我不存储std::async 返回的std::future 时,foo 将在主线程中运行并阻塞它。

std::async(std::launch::async, foo, arg1, arg2);

我在这里错过了什么?

【问题讨论】:

也许async返回的future会被立即销毁。如果future 的析构函数内部有隐式等待,我不会感到惊讶。 【参考方案1】:

来自just::threaddocumentation:

如果策略是 std::launch::async,则在其自己的线程上运行 INVOKE(fff,xyz...)。返回的std::future 将在此线程完成时准备就绪,并将保存返回值或函数调用引发的异常。与返回的std::future 的异步状态相关联的最后一个未来对象的析构函数将阻塞,直到未来准备好。

std::async(std::launch::async, foo, arg1, arg2);

返回的未来不会被分配到任何地方,并且它的析构函数会阻塞,直到 foo 完成。

【讨论】:

【参考方案2】:

我想添加一个链接,指向 Herb Sutter 在 async and ~future 上发表的一篇文章,他认为期货永远不应该阻塞。

【讨论】:

这不是一篇文章,而是一个提案。除此之外,是的,阻止~future() 是一个错误。 ~future() 默认情况下实际上并不阻塞。它仅在从 std::async 返回时才阻塞,因为 async 将阻塞状态分配给 future 并且 ~future() 必须释放它。 > async 将阻塞状态分配给未来...... @WojciechCierpucha 但这是为什么呢?【参考方案3】:

为什么要屏蔽?

    std::async(); 返回 std::future 临时对象 临时对象立即销毁,调用析构函数。 std::future 析构函数正在阻塞。这很糟糕而且很麻烦。

为什么分配是好的?

通过分配给变量,返回的对象不会立即销毁,而是稍后,直到调用代码的范围结束。

代码示例:main1 可以。 main2main3 等效地阻塞了主线程。

void forever() 
    while (true);


void main1() 
    std::future<void> p = std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // can print, then forever blocking


void main2() 
    std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // forever blocking first, cannot print


void main3() 
    std::future<void> p = std::async(std::launch::async, forever);
    std::cout << "printing" << std::endl; // forever blocking first, cannot print

看看cplusplus.com

std::async 的返回值 启动::选择async时,将来返回的未来链接到 创建的线程结束,即使它的共享状态从未被访问过: 在这种情况下,它的析构函数与 fn 的返回同步。 因此,对于异步,不应忽略返回值 行为,即使 fn 返回 void。

【讨论】:

以上是关于当未存储返回值时,std::async 不会产生新线程的主要内容,如果未能解决你的问题,请参考以下文章

std::async()

输入类型日期的占位符(仅当未输入值时)

std::async 不会立即调用

C++11 多线程std:: async与std::thread的区别

为啥 std::future 从 std::packaged_task 和 std::async 返回不同?

主线程等待 std::async 完成[重复]