You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何不持有std::async返回值时主线程会等待其创建的子线程?

关于std::async忽略返回值导致的线程阻塞问题

正常运行的代码与输出

我运行以下代码:

#include <thread>
#include <iostream>
#include <future>

int main() {
    auto fut = std::async(
        std::launch::async, 
        []{
            std::this_thread::sleep_for(std::chrono::seconds(1));
            std::cout << "sub : " << std::this_thread::get_id() << std::endl;
        }
    ); 

    std::cout << "do some on main thread" << std::endl;
    
    fut.get();

    std::cout << "main: " << std::this_thread::get_id() << std::endl;
}

得到输出:

do some on main thread
sub : 139899103246080
main: 139899103250240

这个结果符合预期:因为std::async创建的子线程会先休眠1秒,所以主线程的do some on main thread会先输出。

忽略返回值后的代码与输出

但当我移除存储返回值的变量fut后,出现了不符合预期的行为(此代码仅作实验用途):

#include <thread>
#include <iostream>
#include <future>

int main() {
    std::async(
        std::launch::async, 
        []{
            std::this_thread::sleep_for(std::chrono::seconds(1));
            std::cout << "sub : " << std::this_thread::get_id() << std::endl;
        }
    ); 

    std::cout << "do some on main thread" << std::endl;
    
    std::cout << "main: " << std::this_thread::get_id() << std::endl;
}

输出结果为:

sub : 139716056966912
do some on main thread
main: 139716056971072

看起来主线程会等待子线程完成后,才会输出do some on main thread。同时编译时会收到警告:warning: ignoring return value of function declared with 'nodiscard' attribute [-Wunused-result],C++20起std::async新增了nodiscard属性。

行为原因解析

这并非未定义行为,而是C++标准明确规定的行为:std::async会返回一个std::future对象,当这个对象是临时对象(未被赋值给变量,语句执行完毕后立即销毁)时,其析构函数会阻塞当前线程,直到关联的异步任务执行完成。

你看到的主线程等待子线程的现象,就是因为临时std::future对象在std::async语句结束时被销毁,触发了等待逻辑,导致主线程必须等子线程的休眠和输出完成后,才能继续执行后续的打印语句。

C++20给std::async添加nodiscard属性,正是为了提醒开发者不要忽略这个返回值,避免这种容易让人困惑的隐式阻塞行为。

内容的提问来源于stack exchange,提问作者Takatoshi Kondo

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 21:10:28