作用
内存可见性
多线程共享变量,对于每个线程来说都是内存可见的,借助lock指令前缀实现以下功能:
- 被lock标记的变量cpu缓存地址将会对线程互斥访问
- 写操作完成后会同步刷新缓存到内存
- 写会操作会导致其他线程中的volatile缓存变量无效
- 只保证可见性,不保证原子性
指令重排序
什么是重排序
为了提高程序执行的性能,编译器和执行器(处理器)通常会对指令做一些优化(重排序)
重排序可以分为:
1、编译器重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;
2、处理器重排序。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;
happen-before原则保证了程序的“有序性”,它规定如果两个操作的执行顺序无法从happens-before原则中推到出来,那么他们就不能保证有序性,可以随意进行重排序。(在不影响单线程运行结果的前提下java会进行重排序)
不禁止重排序会有什么问题
1 | class ReorderExample { |
以上面代码为例,如果flag没有加上volatile,那么由于指令重排序1和2的顺序可能颠倒,在多线程环境下A负责写入,B负责读取,则读取结果可能是0.
禁止重排序的原理
在JVM底层volatile是采用“内存屏障”来实现的
volatile变量在字节码级别没有任何区别,在汇编级别使用了lock指令前缀(相当于内存屏障)
- 内存屏障之前/之后的代码不会发生位置转换,确保有序执行
- LOCK 指令前缀促使多线程竞争的环境下互斥地使用这个内存地址
版权声明:本文为博主原创文章,欢迎转载,转载请注明作者、原文超链接,感谢各位看官!!!
本文出自:monkeyGeek
座右铭:生于忧患,死于安乐
欢迎志同道合的朋友一起交流、探讨!
