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

C++使用std::thread多线程执行自增操作大数值下输出异常原因问询

问题原因解析

1. 对join()的功能误解

join()的作用不是让你创建的t1、t2按顺序串行执行,它仅仅是让调用join()的主线程在当前位置阻塞,等待目标子线程执行完毕后再继续向下运行。
你在创建t1、t2的那一刻,两个子线程就已经被操作系统调度开始并行执行,并不是等调用join()时才启动,也不会等t1执行完t2才开始运行,join()完全不会干预子线程之间的执行时序。

2. 结果不稳定的根本原因:竞态条件

你遇到的结果不符合预期是典型的多线程竞态条件问题,和join()是否生效没有任何关系:

  • 你写的m++看起来是一行代码,实际在CPU执行时会被拆分为3步:读取内存中m的当前值到寄存器、寄存器值+1、将新值写回内存
  • 没有同步保护的情况下,两个线程可能同时执行这3步操作,比如线程1读取到m=100、加1为101还没写回时,线程2也读取到m=100、加1为101,最终两个线程都写回101,本该两次自增得到102,实际只加了1,最终结果就会小于预期的2*var
  • 小数值var下结果符合预期的原因是:任务执行时间极短,可能t1在t2被操作系统调度启动前就已经执行完所有操作,两个线程的执行时间没有重叠,刚好没有触发冲突,属于巧合的正确,不是必然结果。

3. volatile的作用误区

这里你用到的volatile完全无法解决多线程同步问题,它的作用仅仅是告诉编译器不要对该变量的读写做指令优化,每次都必须直接从内存读取、直接写回内存,既不保证操作的原子性,也不提供多线程所需的内存屏障,对线程安全没有任何帮助。

修复方案
  • 方案一:将普通变量替换为原子变量,只需修改m的定义即可,原子变量的自增操作原生是线程安全的:
std::atomic<int> m = 0;
  • 方案二:使用互斥锁保护临界区,每次操作m前加锁,操作完成后解锁:
volatile int m = 0;
std::mutex mtx;
void ThdFun(int i)
{
    for (int j = 0; j < i; ++j) {
        std::lock_guard<std::mutex> lock(mtx);
        m++;
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 11:45:04