1.voliate 关键字为什么可以解决可见性和指令重排?
可见性
- 首先,volatile 关键字修饰的共享变量可以提供这种可见性规范,也叫做读写可见。
- 被 volatile 关键字修饰的共享变量在转换成汇编语言时,会加上一个以 lock 为前缀的指令,当CPU发现这个指令时,立即将当前内核高速缓存行的数据回写到内存,同时使在其他内核里缓存了该内存地址的数据无效
- 另外,在早期的 CPU 中,是通过在总线加 LOCK# 锁的方式实现的,但这种方式开销较大。所以Intel开发了缓存一致性协议,也就是 MESI 协议,该解决缓存一致性。
- volatile 的好处,volatile 是一种非锁机制,这种机制可以避免锁机制引起的线程上下文切换和调度问题。所以,volatile 的执行成本比 synchronized 更低。
- volatile 的不足,volatile 关键字只能保证可见性,不能保证原子性操作。
指令重排
```java public volatile boolean sign; descriptor: Z flags: ACC_PUBLIC, ACC_VOLATILE
```
- 从字节码层面,添加 ACC_VOLATILE,在汇编指令的打印会有 lock addl $0x0,(%rsp)s
- 从 JVM 层面,JMM 提供了8个 Happen-Before 规则来约束数据之间竞争、4个内存屏障 (LL LS SL SS)和As-if-serial
- 从硬件层面,sfence、lfence、mfence