Volatile可见性底层实现原理

CPU多级缓存

  • 主内存(RAM):也就是所谓的内存条,一般当数据写入电脑磁盘的时候需要先写入主内存,然后再写入磁盘。

  • 系统主线:连接系统cpu和主内存的系统主线,就比如台式电脑连接主板上连接cpu和内存条的主线。

  • 如下图所示最简单的高速缓存的配置,数据的读取和存储都经过高速缓存,CPU核心与高速缓存有一条特殊的快速通道;主存和高速缓存都连在系统总线上,这条总线还用于其他组件的通信。

  • 高速缓存出现不久,系统变得越来越复杂,高速缓存与主存之间的速度差异被拉大,直到加入了另一级缓存,新加入的这级缓存比第一缓存更大,而且更慢,而且经济上不合适,所以有了二级缓存,甚至是三级缓存。
    在这里插入图片描述
    一、为什么需要CPU多级缓存

  • 在计算机最开始的时候,cpu直接于主内存交换数据,不知道读者对摩尔定律有没有印象:当价格不变时,集成电路上可容纳的元器件的数目,约每隔18-24个月便会增加一倍,性能也将提升一倍,由于cpu性能日新月异的增长,远高于主内存读写,而需要等待主内存,这样发挥不了多核cpu高性能的优势,于是便增加了cpu多级缓存,在现在电脑的任务管理器也是看的到的:

在这里插入图片描述
二、CPU缓存的意义:

  • 时间局部性:如果某个数据被访问,那么在不久的将来它很有可能会被再次访问。
  • 空间局部性:如果某个数据被访问,那么与它相邻的数据很快也能被访问。

三、java线程内存模型

  • java线程内存模型和CPU缓存模型类似,是基于CPU缓存模型来建立的,
    java线程内存模型是标准化的,屏蔽掉了底层不同计算机的区别。

在这里插入图片描述
举个例子:
在这里插入图片描述
输出日志:
在这里插入图片描述
说明了两个线程间读取共享变量存在问题,第二个线程执行完成后initFlag已经置为true;而第一个线程无法获知initFlag已经改变。

在共享变量中加上volatile关键字,保持多线程之间共享变量在多个线程之间工作内存的可见性,则线程1中的initFlag变量同步。
在这里插入图片描述那么volatile 是怎么实现共享变量在多个线程之间工作内存的可见性的呢?

首先来看一下JMM的8种数据原子操作:

  • read 读取,作用于主内存把变量从主内存中读取到本本地内存。
  • load 加载,把从主内存中读取的变量加载到本地内存的变量副本中
  • use 使用,把工作内存中的一个变量值传递给执行引擎,每当虚拟机遇到一个
    需要使用变量的值的字节码指令时将会执行这个操作。、
  • assign 赋值 它把一个从执行引擎接收到的值赋值给工作内存的变量,
    每当虚拟机遇到一个给变量赋值的字节码指令时执行这个操作。
  • store 存储 ,把工作内存中的一个变量的值传送到主内存中,以便随后的write的操作。
  • write 写入 ,它把store操作从工作内存中一个变量的值传送到主内存的变量中。
  • lock 锁定 :作用于主内存的变量,把一个变量标识为一条线程独占状态。
  • unlock 解锁:作用于主内存变量,把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
    在这里插入图片描述
    在这里插入图片描述
  • 线程1:先把initFlag变量read读取出来,再load载入工作内存,use使用线程1执行代码!initFlag
  • 线程2:先把initFlag变量read读取出来,再load载入工作内存,use使用线程2执行代码initFlag=true,
    再assign重新赋值,store存储并写入主内存,write写入到主内存中的变量。(线程2对缓存行lock加锁,
    write写入主内存后会解锁unlock,防止initFlag还未write写入主内存就被线程1读取为false)。
  • 线程1:因为initFlag被volatile修饰,使用MESI缓存一致性协议,线程1cpu总线嗅探机制监听到了
    initFlag值的修改,线程1中initFlag=false失效变为true退出循环继续执行,
    体现了多线程同步运行共享变量副本的可见性。如果initFlag没有被volatile修饰,
    线程1将感知不到initFlag的变化,一直循环下去停止不了。

图中的代码:

在这里插入图片描述

造成jmm缓存不一致的问题解决办法

  1. 总线加锁(性能太低):

    cpu从主内存读取数据到高速缓存,会在总线对这个数据加锁,这样其它cpu没法去读或写这个数据,

    直到这个cpu使用完数据释放锁之后其它cpu才能读取该数据,导致结果:改并行为串行。

在这里插入图片描述

  1. MESI缓存一致性协议

    多个cpu从主内存读取同一个数据到各自的高速缓存,当其中某个cpu修改了缓存里的数据,

    该数据会马上同步回主内存,其它cpu通过总线嗅探机制可以感知到数据的变化从而将

    自己缓存里的数据失效。

在这里插入图片描述在这里插入图片描述

  • 3
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值