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

C++ atomics学习中:race condition为何会出现x输出2,1的情况

2,1输出的产生原理

首先要明确:代码里的非原子++x根本不是不可拆分的原子操作,硬件层面会被拆成3个可被任意打断的独立步骤:

  • 从全局内存加载x的当前值到当前线程绑定的CPU寄存器
  • 在寄存器中对加载到的值做+1计算
  • 把寄存器中的计算结果写回全局内存的x位置

这些步骤的任何间隙,操作系统调度器都可以暂停当前线程、切换CPU运行权;加上多CPU核心的缓存存在延迟,写回内存的操作可以拖很久执行,甚至直接覆盖其他线程已经写好的内存值。

触发2,1输出的完整时序链路:

  1. 初始全局x=0,t1启动执行add:把x=0加载到自己的寄存器,完成+1计算得到结果1,短暂把这个1写回内存让x变成1,随后立刻被调度器挂起,连cout的入口都没走到。此时t1的本地缓存还保留着自增的临时值状态。
  2. 调度器切到t2运行add:t2从内存读到当前x=1,走完完整自增流程,计算得到2并写回内存,此时全局x=2。随后t2执行cout逻辑,打印自己的线程名、当前内存中的x值2——这就是观测到的第一个输出值2。
  3. 之前被挂起的t1被调度回来:因为t1的本地缓存没有收到x已经被修改成2的失效通知,直接把自己缓存中保存的旧自增值1写回内存,把已经是2的全局x覆盖回1。之后t1才进入cout环节,从内存读到现在的x=1,将这个值打印出来——这就是观测到的第二个输出值1。

整个过程没有任何程序错误,只是无同步的非原子变量在多线程下的正常竞态表现,只要存在数据竞争,所有理论上可能的时序组合都有概率被观测到。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.23 21:06:06