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

atomic_thread_fence与atomic exchange交互:双线程能否出现双零值?

原子操作内存序问题分析

代码示例

std::atomic<int> x{0};
std::atomic<int> y{0};

Thread A:
    int y_val = y.load(std::memory_order_acquire);
    if (y_val != 1) {
       int old_x = x.exchange(1, std::memory_order_seq_cst);
       y_val = y.load(std::memory_order_acquire);
    }
    

Thread B:
    y.store(1, std::memory_order_release);
    std::atomic_thread_fence(std::memory_order_seq_cst);
    int x_val = x.load(std::memory_order_relaxed);

问题

两个线程执行完上述代码后,是否可能出现y_val==0且x_val==0的情况?

结论与分析

不可能出现这种情况,具体分析如下:

核心逻辑梳理

线程A只有在第一次y.load(acquire)读到0时,才会进入分支执行x.exchange(1, seq_cst),随后第二次读取y的值;线程B先写入y=1(release语义),再执行一个seq_cst全局栅栏,最后读取x的值(relaxed语义)。

基于seq_cst语义的同步分析

seq_cst(顺序一致)语义要求所有seq_cst操作和seq_cst栅栏在全局范围内有一个统一的执行总序,这是关键约束:

  1. 情况1:线程A的x.exchange(seq_cst)先于线程B的seq_cst栅栏
    此时A已经将x的值改为1,由于seq_cst操作的全局可见性,线程B在栅栏之后的x.load(relaxed)必然能读到x=1,无法满足x_val==0的条件。

  2. 情况2:线程B的seq_cst栅栏先于线程A的x.exchange(seq_cst)
    线程B的y.store(1, release)在栅栏之前执行,seq_cst栅栏会确保这个写操作对所有后续的读操作全局可见。线程A在x.exchange(seq_cst)之后执行的第二次y.load(acquire),必然能读到y=1,无法满足y_val==0的条件。

关于重排的补充说明

线程A中第二次y.load(acquire)和x.exchange(seq_cst)的写操作不会发生重排:x.exchange(seq_cst)本身包含acquire和release语义,且seq_cst操作不允许与后续的内存操作重排,因此第二次读取y的操作不可能被提前到exchange之前,也就不会读到未被更新的y=0。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 04:18:23