https://blog.csdn.net/jjavaboy/article/details/77164474
http://www.infoq.com/cn/articles/ftf-java-volatile
volatile原理
底层是靠一个lock指令来保证顺序性和 可见性
1.lock指令会引起处理器中的工作缓存的数据强制写回到工作内存
2.lock指令会令其它CPU的工作内存中对应的这个共享变量的缓存行无效(在第一步写回内存中后,每个处理器都会有一个嗅探机制,去看自己的工作内存中的数值与主内存中那个的是否一致,不一致,会将自己的工作内存中的数值设置成无效,同时会从主内存中读取数值更新到自己的工作内存中 注:下图中的Cache就是每个CPU的工作内存)
3.禁止指令重排序
lock前缀指令实际上相当于一个内存屏障(也成内存栅栏),内存屏障会提供3个功能:
1)它确保指令重排序时不会把其后面的指令排到内存屏障之前的位置,也不会把前面的指令排到内存屏障的后面;即在执行到内存屏障这句指令时,在它前面的操作已经全部完成;
2)它会强制将对缓存的修改操作立即写入主存;
3)如果是写操作,它会导致其他CPU中对应的缓存行无效。
内存屏障指令帮助vllatile具有可见性和有序性,内存屏障,又称内存栅栏,是一个CPU指令,它的作用有两个,一是保证特定操作的执行顺序,二是保证某些变量的内存可见性(利用该特性实现volatile的内存可见性)。由于编译器和处理器都能执行指令重排优化。如果在指令间插入一条Memory Barrier则会告诉编译器和CPU,不管什么指令都不能和这条Memory Barrier指令重排序,也就是说通过插入内存屏障禁止在内存屏障前后的指令执行重排序优化。Memory Barrier的另外一个作用是强制刷出各种CPU的缓存数据,因此任何CPU上的线程都能读取到这些数据的最新版本。总之,volatile变量正是通过内存屏障实现其在内存中的语义,即可见性和禁止重排优化。
volatile系统级别原理:
全面理解Java内存模型(JMM)及volatile关键字
我是看完这篇文章后,有了自己的一些感悟,如有不对,欢迎指出。
看着两张图,每个任务根据一对一原则对应一个操作系统的内核线程,操作系统将内核线程与CPU进行一一对应,而CPU存在缓存(cpu缓存是对应的线程的工作内存),也就是自己对于主存数据的一份拷贝,会去利用缓存一致性协议保证内存的可见性。
MESI(缓存一致性协议)
它核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。