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

使用Lambda创建线程操作全局变量时的异常输出问题咨询

问题分析与解答

首先澄清你一个关键误解:全局变量传递给引用参数时,完全不需要std::ref()。std::ref()的作用是解决局部变量传递给线程函数引用参数的拷贝问题——线程构造函数会默认拷贝参数,局部变量的拷贝无法绑定到引用,才需要用std::ref包装。但全局变量本身是全局作用域的左值,直接传给int&参数时,就是直接绑定到原变量的引用,你的代码里func(x,z)和func(y,z)确实在操作全局变量的引用,这部分逻辑是没问题的。

那为什么输出会时好时坏?核心问题是你在启动线程后立刻就打印变量,这时候线程可能还没开始执行,或者只执行了一部分,这是典型的竞态条件:

  • 当cout执行时,如果t1和t2都还没抢到CPU时间片,那么x、y、z都是初始的0,输出0,0,0。
  • 如果t1已经启动并执行了几次循环(比如刚完成i=0到3的累加),x和z已经被修改,而t2还没开始运行,就会出现类似9,0,0的输出。

如何得到稳定的预期输出?

你需要把打印操作放到两个线程完全执行完毕之后,也就是在t1.join()和t2.join()之后,确保所有线程的修改都完成:

int main() {
    std::thread t1([]() { func(x, z); });
    std::thread t2([]() { func(y, z); });
    // 先等待两个线程执行完成
    t1.join();
    t2.join();
    // 再打印最终结果
    cout << "x,y,z=" << x << " " << y << " " << z << " " << endl;
    getchar();
    return 0;
}

不过还要注意另一个隐藏问题:两个线程同时修改全局变量z,没有任何同步机制,这会导致数据竞争,z的最终结果是未定义的(多个线程同时读写同一个变量,会出现值覆盖的情况)。如果想得到z的正确累加结果(即两个线程的累加总和),需要用互斥锁保护z的修改:

#include <mutex>
std::mutex mtx;

void func(int& a, int& b) {
    for (int i = 0; i < 10000; ++i) {
        a += i;
        // 用锁保护b的修改,避免数据竞争
        std::lock_guard<std::mutex> lock(mtx);
        b += i;
    }
}

这样才能保证z的结果是两个线程累加值的正确总和。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 06:44:47