多核与内存模型

多核与缓存一致性

MESI 协议

每个 cache line 有 4 个状态:

状态含义
M(Modified)已修改,与内存不一致,本核独占
E(Exclusive)未修改,与内存一致,本核独占
S(Shared)未修改,多个核共享
I(Invalid)无效

状态转换靠总线嗅探(snooping):一个核写,其他核的副本失效。

这是多核性能的隐藏成本:看似独立的数据,只要在同一 cache line,就会反复失效。

内存模型

编译器和 CPU 都会重排指令(为了性能),所以:

// 线程1              // 线程2
x = 1;                while (y == 0) ;
y = 1;                print(x);        // 可能打印 0!

内存序:

序保证
Sequential Consistency完全按程序顺序(最严格,最慢)
Acquire / Release单向屏障
Relaxed只保证原子性,不保证顺序

x86 是 TSO(Total Store Order):store-store 不重排,但 store-load 可能重排(store buffer 导致)。 ARM 更宽松:几乎都可以重排。

C++ 的 std::atomic 让你指定内存序:

std::atomic<int> flag{0};
flag.store(1, std::memory_order_release);      // 前面的写不能移到这之后
int v = flag.load(std::memory_order_acquire);  // 后面的读不能移到这之前

默认 seq_cst 最安全但最慢。理解后再优化。