内存屏障(Memory Barrier)详解与类型
什么是内存屏障(Memory Barrier/Memory Fence)?C++中通过std::atomic::fence实现的内存屏障有哪些类型?为什么在弱内存模型架构(ARM/PowerPC)上内存屏障更加重要?
回答
编译有声
内存屏障定义:CPU指令,控制内存操作的顺序和可见性,禁止编译器或CPU对屏障前后的访存指令做重排序。
四种屏障类型:
- LoadLoad:保证屏障前的所有读操作先于屏障后的读操作完成
- StoreStore:保证屏障前的所有写操作先于屏障后的写操作对其他核心可见
- LoadStore:保证屏障前的读操作先于屏障后的写操作
- StoreLoad:保证屏障前的写操作先于屏障后的读操作(最昂贵,通常需要全屏障)
C++中的std::atomic_thread_fence:
// 释放屏障:本核心所有写操作可见后允许后续写
std::atomic_thread_fence(std::memory_order_release);
// 获取屏障:后续读操作必须在屏障后读取
std::atomic_thread_fence(std::memory_order_acquire);
// 全屏障:seq_cst
std::atomic_thread_fence(std::memory_order_seq_cst);
强模型 vs 弱模型:
- x86(强模型):仅StoreLoad重排可能发生,LoadLoad/StoreStore/LoadStore都不重排——所以acquire/release通常无需额外屏障
- ARM/PowerPC(弱模型):所有四种重排都可能,需要显式
dmb(Data Memory Barrier)指令
编译器屏障 vs CPU屏障:asm volatile("" ::: "memory")是编译器屏障(C++的atomic_signal_fence),只阻止编译器优化,不产生CPU指令。
volatile限制:volatile只阻止编译器重排(不阻止CPU重排),不能作为线程间同步工具。