java关键字volatile规则总结

Owen Jia 2021年03月05日 228次浏览

这次谈的内容属于java并发的知识,基本上java高阶以上的面试必然会问到,如果没问到,只能说明面试官不行...

底层概念:系统内存模型+JMM模型

Java并发编程的几块利器:“synchronized、volatile、reentrantlock、atomic*”,整个java体系差不多就这么了,跳不出这个圈子。

2.jpg

volatile能力

关键字:volatile,加了volatitle的变量将具有2个特性。

1. 对所有线程的可见性

就是当一个线程修改了volatile变量,其他线程是可以立即得知的,普通变量是不行的。但是volatile变量在并发下并不是安全的,虽然它在各个线程内是一致的。

java里面的运算操作符并非原子操作,一个操作符并不一定转换为一个字节码,并且一个字节码也并不一定转换为一个本地机器码指令。

只有满足下面条件的volatile变量是可以不加锁的:

  • 确保只有单一线程修改变量的值
  • 变量不需要和其他状态变量组合使用

2. 禁止指令重排序

指令这个已经涉及到硬件是否支持了。一条语句转成多个字节码,再转成多个机器指令,是1-n-n的转化。cpu内指令执行有自身的优化策略,它保证最终语句依赖和执行结果是对的,但是部分指令会打破顺序的优先执行。首先硬件得支持这个能力,当然目标大多数机器都能支持,哈哈哈。

jdk5以后的volatile完全可以保证指令不会重排序。

volatile使用场景

volatile变量在上与普通变量是没有区别的,反而要慢些,因为有额外的操作成本(新值要立即同步到主内存)。

在变量场景能满足volatile两个特性下,推荐使用volatile,而不是synchronized关键字,因为它的开销要小很多。

并发三特性:原子、可见、有序,适合volatile场景:

  • 状态标记变量适合,保证多线程立即可见。
  • 单例模型中instance适合,规避指令重排序。

推荐阅读

JVM中GC算法总结
Java架构师必备技能之类加载机制
java内存模型规范学习