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

多Release与单Acquire场景下内存序的判定及断言有效性疑问

原子内存序与断言行为分析

示例代码

#include <atomic>
#include <thread>
#include <cassert>
#include <memory>

int i = 0;
std::atomic_int a{0};

int main()
{
    std::thread thr1{[]
    {
        i = 1; // A
        a.store(1, std::memory_order::release); // B
    }};
    std::thread thr2{[]
    {
        while (a.load(std::memory_order::relaxed) != 1); // C
        a.store(2, std::memory_order::release); // D
    }};
    std::thread thr3{[]
    {
        while (a.load(std::memory_order::acquire) != 2); // E
        assert(i == 1); // F
        
    }};
    thr1.join();
    thr2.join();
    thr3.join();
}

你的理解完全正确

断言确实可能成功也可能失败,行为未定义,具体原因如下:

1. 先行发生关系的局限性

已确定的先行发生(happens-before)关系仅存在于:

  • 线程1内部:A(写入i=1)→ B(release语义存储a=1)
  • 线程2内部:C(relaxed语义加载a)→ D(release语义存储a=2)
  • 线程3内部:E(acquire语义加载a=2)→ F(断言i==1)
  • 跨线程:D与E之间存在release-acquire同步,因此D→E属于先行发生关系

但B与C之间不存在任何同步关系:C是relaxed加载,这类操作不提供跨线程的先行发生保证,即便线程2的C读到了线程1的B写入的1,也无法推导出B→C的先行发生关系,线程1中A对i的写入无法同步到线程2。

2. 释放序列规则不适用

关于release-acquire同步的扩展规则(释放序列后续值的同步)要求:后续操作必须是**读-改-写(RMW)**操作(如fetch_add、compare_exchange_strong等)。而线程2的D是单纯的store操作,不属于RMW,因此B到D构不成释放序列,该规则无法生效。

线程3的E仅能保证看到线程2中D之前的操作,无法通过D传递线程1中A的写入,因此执行F时i可能仍为初始值0,断言可能触发失败。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:14:54