Memory-Ordering与屏障

现代 CPU 为了性能,会乱序执行 (Out-of-order Execution) 指令;编译器也会为了优化而重排指令。

危机

acquire 函数中:

  1. 锁变量设为 1 (Locked)。
  2. 临界区代码 (读写共享数据)。

如果 CPU/编译器 认为这两步没有数据依赖,可能会优化成:

  1. 临界区代码 (先执行!)。
  2. 锁变量设为 1。

后果: 你还没锁门,就把家里的东西搬出来了。其他 CPU 会看到未受保护的数据。

解决方案: Memory Barrier

__sync_synchronize() (RISC-V 的 fence 指令)。

  • 语义: 屏障之前的所有内存操作,必须在屏障之后的操作开始之前完成。
  • xv6 在 acquire 拿到锁之后、release 释放锁之前,都加了屏障,强行通过串行化保证逻辑正确。