两点内存语义
1、保证多线程对 变量操作的内存可见性
通过 synchronized 和 Lock 也能够保证可见性,线程在释放锁之前,会把共享变量值都刷回主存,但是相比于 volatile,synchronized 和 Lock 的开销都更大。
2、禁止指令重排序
内存中的语义是通过内存屏障实现:
- 第一个为读操作时,第二个任何操作不可重排序到第一个前面。
- 第一个为写操作时,第二个的读写操作也不运行重排序。
- 第二个为写操作时,第一个任何操作不可重排序到第二个后面。
volatile 的原子性
volatile是线程不安全的: volatile 的两点内存语义能保证可见性和有序性,但是不能保证原子性:对单个 volatile 变量的读/写具有原子性,但是对于类似 volatile++ 这样的复合操作就无能为力了,要想保证原子性,只能借助于 synchronized、Lock 或者并发包下的 atomic 的原子操作类了。
volatile使用场景
(1)状态量标记:这种对变量的读写操作,标记为 volatile 可以保证修改对线程立刻可见,效率也比 synchronized、Lock 有一定的提升。
(2)避免指令重排序
指令重排序会导致,当一条线程访问的 instance 不为 null 时,但是实际上 instance 实例未必已初始化完成,也就造成了线程安全问题。