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

关于C11内存栅栏(memory fence)与原子操作的技术疑问

内存屏障相关疑问解答

先看两段对比代码:

//version 1
Thread A:
    *val = 1;
    atomic_thread_fence(memory_order_release);
    atomic_store_explicit(published, 1, memory_order_relaxed);

Thread B:
    if (atomic_load_explicit(published, memory_order_relaxed) == 1) {
            atomic_thread_fence(memory_order_acquire);
            assert(*val == 1); // will never fail
    }

//version 2
/* Thread A */
    *val = 1;
    atomic_thread_fence(memory_order_release);
    *published = 1;

/* Thread B */
    if (*published == 1) {
        atomic_thread_fence(memory_order_acquire);
        assert(*val == 1); /* may fail */
    }

问题1:atomic_thread_fence是否仅影响原子加载/存储操作?它对编译器和CPU是否都有作用?

  • 不是,atomic_thread_fence的作用范围不局限于原子操作:
    • 对编译器:它会阻止编译器对屏障前后的所有内存操作(无论原子还是非原子)进行重排序,确保屏障前的写操作都被安排在屏障执行前,屏障后的操作在屏障执行后。
    • 对CPU:它会生成硬件级别的内存屏障指令,阻止CPU对屏障前后的内存操作进行乱序执行,同样覆盖所有类型的内存操作。
      本质上它是全局的内存操作约束,而非仅针对原子API。

问题2:在版本2中,对published的存储是非原子操作,为何使用atomic_thread_fence仍会导致断言失败?

首先纠正误解:atomic_thread_fence并非“仅针对原子操作”,但版本2断言失败的核心原因是:

  • 线程A对published的非原子写,无法和线程B对published的非原子读形成synchronize-with(同步关系)。
  • 版本1中,原子存储atomic_store_explicit和原子加载atomic_load_explicit配合release/acquire屏障,能建立跨线程同步:线程A屏障前的*val=1会被线程B在屏障后可靠可见。
  • 而版本2里,非原子的读写操作本身不保证可见性,CPU可能缓存val的值未同步到主存,或编译器对非原子操作做了优化导致值未及时更新,即使加了屏障也无法弥补非原子操作缺失的同步语义。

问题3:为何*val = 1未写成atomic_store_explicit(val, 1, memory_order_relaxed)?

  • val的操作不需要原子语义:在版本1的同步机制下(release/acquire屏障+原子published操作),线程B只有在确认published被原子设置后才会读取val,此时线程A对val的写操作已完成,且通过屏障保证了可见性。
  • 使用普通非原子写更高效:原子操作会带来额外的CPU同步开销,在不需要原子语义的场景下,普通内存操作完全满足需求且性能更好。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.26 03:23:01