JMM(java内存模型)的讲解与缓存不一致问题

一.内存模型的工作流程

JMM三大特性:可见性、原子性、有序性
JMM(Java内存模型)本身是一种抽象的概念并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。
如下图:
在这里插入图片描述
这个就是JMM内存模型的大致图,从其中可反映出工作内存与主内存之间变量的同步都是通过JMM进行控制的,程序通过4组对数据的原子操作保证了赋值的操作的进行,下面让我们来分析一下JMM通过这4组操作的执行过程:
在这里插入图片描述
read(读取):把变量值从主内存中读取出来。
load(加载):把读取出来的变量值加载到工作内存中。
use(使用):把工作内存的变量值读取出来进行计算。
assgin(赋值):把计算的值赋值到工作内存中。
store(存储):将工作变量的值存储到主内存中。
wirte(写入):将store过去的变量值赋值到主内存中的变量中去。
lock(锁定):将主内存进行加锁操作,使其变为独占状态。
unlock(解锁):将主内存进行解锁,使其他线程可以把他变为独占状态。

二.缓存不一致问题

通过这4个虽然能使值进行传递,但在多线程的情况下仍会出现问题,如果一个线程在另一个线程读取并计算的阶段也进行了值的修改,就会造成缓存不一致的情况发生,这时两个线程所产生的数据就会不一样。针对这种情况的产生,可以有两种方法进行解决:
(一)总线加锁:cpu从主内存读取数据到高速缓存的过程中,会在总线进行加锁,这样当其中一个线程进行操作的时候会变为独占,其他线程不允许进行读取或写入的操作。但并不推荐这种做法,因为比较浪费CPU的性能。
(二)MESI缓存一致性协议:多个CPU从主内存读取同一个数据到各自的高速缓存,当其中某个CPU修改了缓存里的数据,该数据会马上同步回到主内存,其他的CPU通过总线嗅探机制可以感知到数据变化从而将自己缓存里的数据失效。
在这里插入图片描述

三.MESI缓存一致性协议的底层实现

在多核CPU中,内存中的数据会在多个核心中存在数据副本,某一个核心发生修改操作,就产生了数据不一致的问题,而一致性协议正是用于保证多个CPU cache之间缓存共享数据的一致性。

cache的写操作
write through 写通
每次CPU修改cache中的内容会立即更新到内存,也就意味着每次CPU写共享数据,会导致总线事务,因此这种方式常常会引起总线事务的竞争,虽然后高的一致性但是效率非常低。
write back 写回
每次CPU修改了cache中的数据,不会立即更新到内存,而是等到cache line在某一个必须或合适的实际才会更新到内存。

写失效
当一个CPU修改了数据,如果其他CPU有该数据,则通知其为无效;
写更新
当一个CPU修改了数据,如果其他CPU有该数据,则通知其更新;

但光使用Cache并不能保证:
**1.**多核情况下,所有的cpu操作都会涉及缓存一致性的校验,只不过该协议是弱一致性,不能保证一个线程修改变量后,其他线程立马可见,也就是说虽然其他CPU状态已经置为无效,但是当前CPU可能将数据修改之后又去做其他事情,没有来得及将修改后的变量刷新回主存,而如果此时其他CPU需要使用该变量,则又会从主存中读取到旧的值。而volatile则可以保证可见性,即立即刷新回主存,修改操作和写回操作必须是一个原子操作;
**2.**正常情况下,系统操作并不会进行缓存一致性的校验,只有变量被volatile修饰了,该变量所在的缓存行才被赋予缓存一致性的校验功能。

Volatile的底层实现:
1)内存屏障:可禁止指令重排序,这样就可以防止多线程的情况下另一个线程读取到对象半初始化状态时赋值为0的情况,强制按照现有排序过程进行操作。
2)可见性:底层实现主要通过汇编lock前缀指令,他会锁定这块内存区域的缓存并回写到主内存。相当于会将当前处理器缓存行的数据立即写回到系统内存,这个写回内存的操作会引起在其他CPU缓存了该内存地址的数据无效(MESI协议)。

通过这种方式既可以提高性能,又可以解决缓存不一致的问题。好了,今天的分享就结束了,如果有欠缺的地方,希望指教。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值