可见性:指在多线程情况下,某一线程对变量进行更改后,其余线程能够立即知晓
指令重排:JVM 对指令进行优化自动安排自指令顺序
volatile,final,synchronized 都能实现可见性
volatile 的本质是在告诉 JVM 当前变量在寄存器中的值是不确定的,需要在主存中读取,synchronized 则是锁定,只有当前线程可以访问变量,其他线程被阻塞
volatile 只能使用在变量级别,synchronized 可以使用在变量、方法
volatile 只能保证变量修改的可见性,但不能保证变量修改的原子性,而synchronized 可以保证变量修改的可见性和原子性
volatile 不会造成线程的阻塞,而 synchronized 会造成线程的阻塞
volatile 标记的变量不会被编译器优化,而 synchronized 标记的变量可以被编译器优化
使用 volatile 需要满足的条件:
运算结果不依赖于变量的当前值,或者保证只有一个线程修改变量的值
不需要与其他状态变量参与不变约束
在访问变量时不需要加锁
volatile 的不变性
将当前处理器缓存的数据回写到系统内存
这个写回内存的操作会造成其他 cpu 里缓存了该内存地址的数据无效
volatile 变量在赋值之后会有一个 lock add 指令,这个指令相当于内存屏障,重排序时不能将屏障后的指令排序到屏障之前
volatile 禁止指令重排序:普通变量仅会保证在方法的执行过程中所有依赖赋值结果的地方都能获取到正确的结果,而不能保证变量的赋值操作顺序与程序代码中的操作顺序一致
volatile保证可见性:add 指令会使得其他工作线程的工作内存缓存的数据失效