内存屏障:Memory Barrier(Memory Fence)
● 可见性
○ 写屏障(sfence)保证在该屏障之前的,对共享变量的改动,都同步到主存当中
○ 而读屏障(lfence)保证在该屏障之后,对共享变量的读取,加载的是主存中最新数据
● 有序性
○ 写屏障会确保指令重排序时,不会将写屏障之前的代码排在写屏障之后
○ 读屏障会确保指令重排序时,不会将读屏障之后的代码排在读屏障之前
volatile 原理
● volatile 的底层实现原理是内存屏障,Memory Barrier(Memory Fence)
● 对 volatile 变量的写指令后会加入写屏障
● 对 volatile 变量的读指令前会加入读屏障
● volatile 只可以保证可见性和有序性,不能保证原子性。只适用于一个线程写,多个线程读的情况,还适用于double-checked locking 单例模式的优化。首选synchronized解决和预防线程安全问题。
public void actor2(I_Result r) { num = 2; ready = true; // ready 是 volatile 赋值带写屏障 // 写屏障 }
public void actor1(I_Result r) { // 读屏障 if(ready) {// ready 是 volatile 读取值带读屏障 r.r1 = num + num; } else { r.r1 = 1; } }
参照图片理解:
对volatile变量的赋值带写屏障,使得写入i和j的指令不会被重排序到putstatic k之后。