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

IRIW场景下C++原子操作多线程无输出的根本原因问询

IRIW场景下双线程无打印现象的根因解释

你提到的是典型的独立读独立写(Independent Read Independent Write, IRIW) 内存序问题,你猜测的编译器重排序不是该现象的根本原因,具体逻辑如下:

先明确基础语义约束

首先你对acquire内存序的重排序规则理解有误:std::memory_order_acquire的语义是禁止本线程内排在acquire操作之后的所有读写操作,被重排到acquire操作之前执行。所以func_4中while循环的y.load(std::memory_order_acquire),一定发生在后续的x.load(std::memory_order_acquire)之前,编译器不可能把这两个load操作重排,你的猜想不成立。

真实根因:跨核心的存储可见性顺序差异

release-acquire的同步机制,只能保证「发起release写的线程,在该写操作之前的所有本线程操作,对执行对应acquire读的线程可见」,但它完全不保证不同线程看到的多个独立release写操作的全局顺序是一致的。
你假设的「func1写x → func3读到x → func2写y → func4读到y」是上帝视角的全局执行顺序,但在弱内存模型硬件(如ARM、PowerPC)上,不同核心的缓存一致性传播可以存在顺序差异:

  • 运行func3的核心,先观测到x的release写入,后观测到y的release写入
  • 运行func4的核心,先观测到y的release写入,后观测到x的release写入
    此时就会触发你提到的双线程无打印现象:
  1. func3退出while循环时,已经观测到x=true,但此时还没观测到y的写入,所以if判断y.load返回false,不打印
  2. func4退出while循环时,已经观测到y=true,但此时还没观测到x的写入,所以if判断x.load返回false,也不打印

复现与修复方案

  • 该现象完全符合C++标准对release/acquire内存序的语义约束,在弱内存模型硬件上可以稳定复现
  • 如果要禁止该现象,需要把所有原子操作的内存序替换为std::memory_order_seq_cst,该内存序会强制所有线程看到的所有seq_cst操作的全局顺序完全一致,保证两个线程中至少有一个会打印输出。

相关复现代码

std::atomic<bool> x,y;
void func_1() {
  x.store(true, std::memory_order_release);
}
void func_2() {
  y.store(true, std::memory_order_release);
}
void func_3() {
  while(!x.load(std::memory_order_acquire));
  if(y.load(std::memory_order_acquire)) {
    std::cout << "x == true then also y == true \n"; 
  }
}
void func_4() {
  while(!y.load(std::memory_order_acquire));
  if(x.load(std::memory_order_acquire)) {
    std::cout << "y == true then also x == true \n";
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.05 22:12:02