volatile是在并发编程中保证共享数据一致性的常用关键字,同时也能保证多线程中共享数据的可见性、指令的有序性。
我们知道,每个线程在执行时,都有自己独立的工作内存,用于存放线程执行时涉及到的一些变量,这些变量其实都是主存中相关变量的副本,在线程执行完毕后更新变量的值到主内存中。如果多个线程之间变量需要共享那么只能通过主内存来实现。
例如A、B两个线程在执行的时候都涉及到了X变量,那么A、B两个线程都会从住内存中获取X变量,存入各自的工作内存中,其实X就属于共享数据。如果X=10,A中对X变量重新赋值为X=X+1,B中也对X变量重新赋值为X=X+1,按照我们的设想,两个线程执行完毕后X应该为12,但是并非如此,由于A、B更新的都是他们各自工作内存中X(X=10),A更新完毕后,B并不知道A已经更新了,所以B的X=X+1还是在X=10的基础上进行操作的,最后更新到住内存的X都是11。这就导致数据的不准确。
上述情况就是在并发编程中没有保证“可见性”而导致的,为了保证“可见性”,我们可以用volatile关键字来修饰共享数据。
使用volatile的两层语意:
语意一:被volatile修饰的变量在被修改后,会被强制更新到主内存,并且让其他工作内存中的相关副本失效,其他工作内存再使用的时候只能去住主内存中重新拿取最新的值。从而保证了“可见性”。
语意二:禁止重排序,从而保证了“有序性”。
“可见性”、“有序性”的理解可参考:https://blog.youkuaiyun.com/Peacock__/article/details/93601133
通过观察volatile变量和普通变量所生成的汇编代码可以发现,操作volatile变量会多出一个lock前缀指令。
这个lock前缀指令可以理解为内存屏障,提供了上述的语意一保证。