volatile的内存语义
volatile变量有两种特性:
- 保证此变量对所有的线程的可见性;
- 禁止指令重排序优化。
简单来说,把对volatile变量所有的单个读/写,看成是使用了同一个锁对这些单个的读/写操作进行了同步,当然,实现上并不是这样的。volatile变量是JVM提供的最轻量的同步机制。
volatile变量实现机制:
转换成指令的时候,我们可以发现,volatile变量在每次save操作的时候,和普通的变量相比,都会多一个lock命令,这个命令会使得发生以下两件事:
- 将当前处理器缓存行的数据协会到内存系统;
- 这个写回内存的操作会使得其他CPU里缓存的该内存地址的数据失效。
volatile变量在不满足以下两条规则的运算场景中的使用都需要通过加锁来实现同步:
- 运算结果并不依赖变量的当前值,或者能够确保只有单一的线程修改变量的值;
- 变量不需要与其他的状态变量共同参与不变约束。
针对上面说的1)我们可以知道为何对于volatile修饰的int变量直接做加一或者减一的操作是线程不安全的了,因为运算结果依赖当前值。
volatile变量写的内存语义:
当写一个volatile变量的时候,JMM会把该线程对应的工作内存中的共享变量值刷新到新的主内存。
volatile变量读的内存语义:
当读一个volatile变量的时候,JMM会把该线程对应的工作内存设置为无效,线程接下来从主内存中读取对应的变量。