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

为何std::async同时指定async|deferred时deferred未延迟执行?

问题与解答

测试代码

#include <future>
#include <string>
#include <iostream>
#include <chrono>
#include <thread>

using namespace std::chrono_literals;

int main() {
    int v = 0;

    auto a1 = std::async(
        std::launch::async | std::launch::deferred, [&v]() {
            std::cout << "begin 1" << std::endl;
            std::cout << "v = " << v << std::endl;
            std::this_thread::sleep_for(100ms);
            std::cout << "end 1" << std::endl;
    });

    auto a2 = std::async(
        std::launch::async | std::launch::deferred, [&v]() {
            std::cout << "begin 2" << std::endl;
            std::this_thread::sleep_for(200ms);
            v = 123;
            std::cout << "end 2" << std::endl;
    });

    a2.wait();
    // 我原本认为a1会在此处才开始执行?
    // 这样v应该输出123而非0?
    a1.wait();

    return 0;
}

问题描述

使用std::launch::async | std::launch::deferred组合策略调用std::async时,观察到a1与a2并发执行,且v输出为0;但仅使用deferred策略时,程序表现符合预期(先执行a2修改v为123,再执行a1输出123)。想明确:为何会出现这种差异?async策略是否会影响deferred的行为?

解答

这是C++标准对std::async组合策略的规定直接导致的:

  • 当同时指定std::launch::async和std::launch::deferred时,标准库实现拥有完全选择权——它可以选择立刻在新线程中执行任务(遵循async策略),也可以选择延迟到调用wait()或get()时再执行(遵循deferred策略)。标准没有强制要求优先使用deferred,实现会根据系统资源、线程池负载等情况自行决策。
  • 你的测试中,标准库选择了对a1和a2都采用async策略,因此两个任务在创建后就立刻在后台线程并发执行了。a1执行输出v时,a2还在200ms的sleep过程中,尚未修改v,所以输出0。
  • 当仅指定std::launch::deferred时,任务会严格遵循延迟执行规则:只有调用wait()或get()时,任务才会在当前调用线程(主线程)中同步执行。因此你先调用a2.wait(),a2执行完毕修改v为123,之后a1.wait()触发a1执行,此时v已经是123,符合预期。

总结:如果必须保证任务延迟执行,只能单独指定std::launch::deferred,不能与async策略组合——组合策略下的行为是不确定的,完全由标准库实现决定。

内容的提问来源于stack exchange,提问作者lk.c

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.24 14:27:13