【问题标题】:std::async won't spawn a new thread when return value is not stored当未存储返回值时,std::async 不会产生新线程
【发布时间】: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 的析构函数内部有隐式等待,我不会感到惊讶。

标签: c++ multithreading asynchronous


【解决方案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】:

    为什么要屏蔽?

    1. std::async(); 返回 std::future 临时对象
    2. 临时对象立即销毁,调用析构函数。
    3. 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。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-07-13
      • 1970-01-01
      • 1970-01-01
      • 2014-11-15
      • 2023-02-16
      • 2017-01-23
      • 1970-01-01
      相关资源
      最近更新 更多