先说说volatile的三个性质吧(过眼也行):
1.可见性;
2.不保证原子性;
3.禁止指令重排序;
再继续深入volatile之前,再来谈谈Java内存模型(JMM)
JMM的三个性质:
1.原子性;
2.可见性;
3.有序性;
这三个性质也是并发无法避免的问题。
好了回归正题,继续说volatile。
在线程操作共享变量,即上图主内存中的变量时,会先拷贝一份到本线程的工作内存,然后再对其操作。但这样也带来一个问题,就是其中一个线程对这个共享变量修改后,其他线程无法立即感知这个变化,仍使用修改前的值进行操作,那这样的操作就显得无意义甚至不安全。
所以使用了volatile来修饰共享变量,它的作用就是保证了对其他线程的可见性,原理就是当线程修改共享变量的值的时候,会将该共享变量刷新回主内存,其他线程立即感知到共享变量已改变,则重写读取共享变量的值。进而volatile保证了可见性。
volatile不保证原子性是因为volatile的底层实现并不是OS中的原语操作(即原子性操作),所以要想保证原子性,可以使用JUC包下的原子类。
volatile禁止指令重排的语义:
在执行程序时为了提高性能,编译器和处理器通常会对指令做重排序:
编译器重排序。编译器在不改变单线程程序语义的前提下,可以重新安排语句的执行顺序;
处理器重排序。如果不存在数据依赖性,处理器可以改变语句对应机器指令的执行顺序;
网友评论