多核处理器系统中内存一致性问题举例

单核处理器系统中 store buffer 的可见性 这里说了 单核情况下 一个示例程序 因为 两点的存在导致的 内存一致性问题

  1. store 指令 从 store buffer “出队” 的顺序 不能保证先入先出
  2. Store Buffer Forwarding 有限制条件,在部分情况下不能Forwarding
  • 即 在 X86 下 ,单核不存在内存一致性问题 ,但在ARM/riscv 下,单核存在内存一致性问题
  • 那么 我们将其 扩展为多核 ,如果 单核 存在内存一致性问题, 那么 多核照样存在内存一致性问题

不过我们 提出一个新的 场景 , 即多核场景下的 因为一个新的原因导致的 内存一致性问题,原因为

  1. 不保证写的顺序可见性
多核场景下,有cache,有store buffer  
一开始内存中 ready 为 0 , data 为 0

// 用户函数     运行在 core 0 
data  = 123;  // S1
ready = 1  ; // S2

// 用户函数     运行在 core 1 
if (ready == 1) {
    assert(data == 123);
}

此时我们假设 store 指令 按照 程序编码顺序 "出队", // 虽然在 弱一致性模型中,这个不能保证
那么 assert 会失败吗?
虽然 在core 0 而言指令 S1 和 S2 按照程序顺序提交,在core1看来其顺序未必相同
例如
	对 ready 的写可能会较快的传播到处理器1(可能因为缓存命中)
	而对 data 的写 可能会比较慢地传播到处理器1(可能因为缓存缺失)

🧠 反方观点1 : 我认为 不管快慢, 都是会读到的, 只会导致 流水线 stall 而已 , 所以 assert 不会失败

你说的“流水线 stall,等到读到再继续”,这种理解适用于单核或强一致模型(如 x86),但在 多核弱一致模型中,读取操作不会 stall 去等待一致性,而是读取当前可见的值

✅ 在弱一致模型中(如 ARM/RISC-V):

  • Core 0data=123 写入其 store buffer → cache
  • 紧接着 ready=1 也写入其 cache;

这两次写入虽然在 Core 0 看是顺序的,但:

  • Core 1 在访问 ready 时,如果它的 cache 失效,会向系统请求 ready 的缓存行,可能很快被刷新到了内存并响应;
  • data 对应的缓存行可能还没刷新或系统没有通知 Core 1 其缓存无效(Invalidate Miss);
  • 所以 Core 1 在这时看到了 ready==1,却还没看到 data==123

这就出现了你说的那个令人惊讶的情况:

if (ready == 1) {
    assert(data == 123); // 这里失败
}

✅ 为什么会这样?根本原因是内存模型

架构是否允许这种乱序可见性(S2可见但S1不可见)
x86❌ 不允许:Store 被强制顺序可见(TSO)
ARM✅ 允许:Weak Ordering
RISC-V✅ 允许:Weak Ordering

所以在 ARM/RISC-V 上,除非你加上 memory barrier(内存屏障),否则确实可能出现:

  • data 还没传播出去,
  • ready 已经传播到其他核,
  • 导致其他核看到不一致状态。

✅ 为什么不“stall”等待写都可见呢?

因为:

  • 读取操作不是同步操作,不会等待写入同步完毕。
  • 多核系统设计目标是并发性和性能,不会为了“等待另一个核心的数据刷新”而主动阻塞读取。
  • 如果需要保证顺序,需要**人为添加屏障(memory barrier)**或用同步机制(如锁、原子操作)。

✅ 如果你希望 assert 不失败,该怎么做?

在 Core 0 上:

data = 123;
dmb();         // 数据内存屏障,确保 data 的写对其他核心可见
ready = 1;

或用 C11 原子写:

atomic_store_explicit(&data, 123, memory_order_relaxed);
atomic_store_explicit(&ready, 1, memory_order_release);

在 Core 1 上:

if (atomic_load_explicit(&ready, memory_order_acquire)) {
    assert(atomic_load_explicit(&data, memory_order_relaxed) == 123);
}

这种用法利用了 release-acquire 同步语义,能确保 Core1 在看到 ready==1 后,也看到之前的 data 写。


✅ 总结

问题是否成立说明
多核系统会 stall 直到看到一致的数据不会,读取会看到“当前可见的值”,不等于等待一致
store buffer 是 FIFO,所以写顺序一致✅/❌顺序进入 store buffer,但何时对其他核心可见不一定顺序
传播快慢是否只是影响延迟在弱一致模型下,传播差异导致可见顺序乱序,进而出现 assert 失败
assert(data == 123) 会失败吗✅ 可能在 ARM/RISCV 等架构上,确实可能,如果没有内存屏障
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值