揭示volatile背后的奥秘——CPU多级缓存与CPU指令重排

Volatile的做用



Volatile是如何保证内存可见性的?

CPU多级缓存

CPU的运行速度很是快,而对磁盘的读写IO速度却很慢,为了解决这个问题,有了内存的诞生;java

而CPU的速度与内存的读写速度之比仍然有着100 : 1的差距,为了解决这个问题,CPU又在内存与CPU之间创建了多级别缓存:寄存器、L一、L二、L3三级缓存。缓存

CPU三级缓存.png 并发

CPU缓存一个最小单位是64Byte:通过实践得出,缓存64Byte是一个较为合适的单位大小,不会由于缓存过大,而使得读取速度下降,也不会由于缓存过少,而屡次去读取数据。app

核心1核心2在操做同一缓存行中的不一样元素时,即便是操做的不一样元素不会相互形成影响,可是,同一缓存行数据若被修改,则会经过缓存一致性协议来使其余CPU与核心中的缓存失效,从而从新去内存中读取数据,形成程序速度变慢。框架

  • 奇技淫巧:在这种状况下,经过“补齐”一块64Byte大小的空间,来使得缓存不会由于一致性问题而重复更新。spa

  • 实际应用场景:线程

    • disruptor并发框架
    • JDK8能够用注解 @Sun.misc.Contended实现两个对象或者变量绝对不在同一块缓存行内。



CPU为何会指令重排?

咱们的程序运行时,会被编译器转化成一条一条CPU可以执行的语句,例以下面的程序:code

int a = 1;
int b = 1;

a = a + b;
a++;
复制代码

简单地观察便可发现,第4行与第5行的语句交换顺序执行并不会发生最终结果的不一致。cdn

这为CPU指令重排提供了重排的可行性!对象

而根本缘由是:CPU运行速度与内存读取速度不匹配,第4行的语句会让CPU到内存中寻找b的值,从而使CPU空闲时间过多,而考虑到效率问题,CPU就在这一段读取内存的空闲时间内,先执行了下一条语句,提升程序运行效率。


不容许重排序状况:
  • happen-before:六项规则

  • as if serial:单线程执行结果不能被改变

  • DCL(Double Check Lock)单例模式:防止对象未建立完成,就已经被另外一个线程返回了

  • ……


volatile 内存屏障hot spot实现:

lock cpu总线,使CPU缓存中的数据失效,使得其余CPU暂时中止工做达到防止指令重排序。

相关文章
相关标签/搜索