硬件层提供了一系列的内存屏障 memory barrier / memory fence(Intel的提法)来提供一致性的能力。拿 X86 平台来说,有几种主要的内存屏障:
- lfence,是一种 Load Barrier 读屏障
- sfence, 是一种 Store Barrier 写屏障
- mfence, 是一种全能型的屏障,具备 lfence 和 sfence 的能力
- Lock 前缀,Lock 不是一种内存屏障,但是它能完成类似内存屏障的功能。Lock 会对 CPU 总线和高速缓存加锁,可以理解为 CPU 指令级的一种锁。它后面可以跟 ADD, ADC, AND, BTC, BTR, BTS, CMPXCHG, CMPXCH8B, DEC, INC, NEG, NOT, OR, SBB, SUB, XOR, XADD, and XCHG 等指令。
内存屏障有两个能力:
- 阻止屏障两边的指令重排序
- 刷新处理器缓存/冲刷处理器缓存
对 Load Barrier 来说,在读指令前插入读屏障,可以让高速缓存中的数据失效,重新从主内存加载数据
对 Store Barrier 来说,在写指令之后插入写屏障,能让写入缓存的最新数据立即写回到主内存
Lock 前缀实现了类似的能力,它先对总线和缓存加锁,然后执行后面的指令,最后释放锁后会把高速缓存中的数据刷新回主内存。在 Lock 锁住总线的时候,其他 CPU 的读写请求都会被阻塞,直到锁释放。
不同硬件实现内存屏障的方式不同,Java 内存模型屏蔽了这种底层硬件平台的差异,由 JVM 来为不同的平台生成相应的机器码。
