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

为何WSL2中运行该C++多线程程序会重复打印'thread 1 exists'?

WSL2下C++多线程printf重复输出问题分析与解决

问题现象

运行以下C++多线程程序时,thread 1 exists被重复打印两次,不符合每个线程仅输出一次退出信息的预期。

程序代码

#include <atomic>
#include <condition_variable>
#include <cstdio>
#include <cstdlib>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <thread>
#include <iostream>
#include <future>

std::atomic<int> g_Flag = 0;
std::atomic<int> cnt = 0;

void worker1(std::future<int> fut) {
    printf("this is thread 1\n");
    g_Flag = 1;
    cnt++;
    fut.get();
    printf("thread 1 exists\n");
}

void worker2(std::promise<int> prom) {
    printf("this is thread 2\n");
    g_Flag = 2;
    cnt++;
    prom.set_value(10);
    printf("thread 2 exists\n");
}

using namespace std::chrono_literals;
int main() {
    std::promise<int> prom;
    std::future<int> fut = prom.get_future();
    std::thread t1(worker1, std::move(fut));
    std::thread t2(worker2, std::move(prom));
    while (cnt.load() != 2) {

    }
    t1.detach();
    t2.detach();
    printf("main exists\n");
    return 0;
}

实际输出

eugene@DESKTOP-P8P395D:~/tron$ ./a.out 
this is thread 1
this is thread 2
main exists
thread 2 exists
thread 1 exists
thread 1 exists

原因分析

这个问题并非WSL2环境本身的问题,而是程序同步逻辑存在缺陷,触发了未定义行为:

  • 主线程的while (cnt.load() != 2)仅能确认两个线程执行到了cnt++的位置,但无法保证线程已经完成后续的printf操作。
  • 主线程调用detach后立即return 0,进程会触发终止流程。此时操作系统会强制终止所有仍在运行的分离线程,如果子线程正处于printf的IO操作过程中,stdio缓冲区的异常处理会导致重复输出这类未定义行为。

解决方向

  1. 替换detach为join(推荐):
    这是最安全的方案,主线程等待所有子线程完全执行完毕后再退出,从根本上避免进程提前终止导致的子线程IO异常。修改main函数:

    int main() {
        std::promise<int> prom;
        std::future<int> fut = prom.get_future();
        std::thread t1(worker1, std::move(fut));
        std::thread t2(worker2, std::move(prom));
        // 等待子线程执行完成
        t1.join();
        t2.join();
        printf("main exists\n");
        return 0;
    }
    
  2. 完善同步机制(若必须使用detach):
    添加额外的同步变量(比如std::atomic<int>),让主线程等待所有子线程完成所有操作后再退出,而不是仅等待cnt==2。例如:

    • 添加全局变量std::atomic<int> done_cnt = 0;
    • 在每个线程的最后一行添加done_cnt++;
    • 主线程替换等待逻辑为while (done_cnt.load() != 2) {},确保子线程完全执行完毕后再detach并退出。

内容的提问来源于stack exchange,提问作者Eadren King

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.27 00:34:52