内存模型是怎么解决缓存一致性的

转载自  内存模型是怎么解决缓存一致性的

在再有人问你Java内存模型是什么,就把这篇文章发给他这篇文章中,我们介绍过关于Java内存模型的来龙去脉。

我们在文章中提到过,由于CPU和主存的处理速度上存在一定差别,为了匹配这种差距,提升计算机能力,人们在CPU和主存之间增加了多层高速缓存。每个CPU会有L1、L2甚至L3缓存,在多核计算机中会有多个CPU,那么就会存在多套缓存,那么这多套缓存之间的数据就可能出现不一致的现象。为了解决这个问题,有了内存模型。内存模型定义了共享内存系统中多线程程序读写操作行为的规范。通过这些规则来规范对内存的读写操作,从而保证指令执行的正确性。

不知道小伙伴们有没有想过这样的问题:内存模型到底是怎么保证缓存一致性的呢?

接下来我们试着回答这个问题。首先,缓存一致性是由于引入缓存而导致的问题,所以,这是很多CPU厂商必须解决的问题。为了解决前面提到的缓存数据不一致的问题,人们提出过很多方案,通常来说有以下2种方案:

1、通过在总线加LOCK#锁的方式。

2、通过缓存一致性协议(Cache Coherence Protocol)。

在早期的CPU当中,是通过在总线上加LOCK#锁的形式来解决缓存不一致的问题。因为CPU和其他部件进行通信都是通过总线来进行的,如果对总线加LOCK#锁的话,也就是说阻塞了其他CPU对其他部件访问(如内存),从而使得只能有一个CPU能使用这个变量的内存。在总线上发出了LCOK#锁的信号,那么只有等待这段代码完全执行完毕之后,其他CPU才能从其内存读取变量,然后进行相应的操作。这样就解决了缓存不一致的问题。

但是由于在锁住总线期间,其他CPU无法访问内存,会导致效率低下。因此出现了第二种解决方案,通过缓存一致性协议来解决缓存一致性问题。

 

 

缓存一致性协议

缓存一致性协议(Cache Coherence Protocol),最出名的就是Intel 的MESI协议,MESI协议保证了每个缓存中使用的共享变量的副本是一致的。

MESI的核心的思想是:当CPU写数据时,如果发现操作的变量是共享变量,即在其他CPU中也存在该变量的副本,会发出信号通知其他CPU将该变量的缓存行置为无效状态,因此当其他CPU需要读取这个变量时,发现自己缓存中缓存该变量的缓存行是无效的,那么它就会从内存重新读取。

在MESI协议中,每个缓存可能有有4个状态,它们分别是:

M(Modified):这行数据有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。

E(Exclusive):这行数据有效,数据和内存中的数据一致,数据只存在于本Cache中。

S(Shared):这行数据有效,数据和内存中的数据一致,数据存在于很多Cache中。

I(Invalid):这行数据无效。

关于MESI的更多细节这里就不详细介绍了,读者只要知道,MESI是一种比较常用的缓存一致性协议,他可以用来解决缓存之间的数据一致性问题就可以了。

但是,值得注意的是,传统的MESI协议中有两个行为的执行成本比较大。

一个是将某个Cache Line标记为Invalid状态,另一个是当某Cache Line当前状态为Invalid时写入新的数据。所以CPU通过Store Buffer和Invalidate Queue组件来降低这类操作的延时。

如图:

 

当一个CPU进行写入时,首先会给其它CPU发送Invalid消息,然后把当前写入的数据写入到Store Buffer中。然后异步在某个时刻真正的写入到Cache中。

当前CPU核如果要读Cache中的数据,需要先扫描Store Buffer之后再读取Cache。

但是此时其它CPU核是看不到当前核的Store Buffer中的数据的,要等到Store Buffer中的数据被刷到了Cache之后才会触发失效操作。

而当一个CPU核收到Invalid消息时,会把消息写入自身的Invalidate Queue中,随后异步将其设为Invalid状态。

和Store Buffer不同的是,当前CPU核心使用Cache时并不扫描Invalidate Queue部分,所以可能会有极短时间的脏读问题

所以,为了解决缓存的一致性问题,比较典型的方案是MESI缓存一致性协议。

MESI协议,可以保证缓存的一致性,但是无法保证实时性。

 

 

内存模型

前面介绍过了缓存一致性模型,接着我们再来看一下内存模型。我们说过内存模型定义一系列规范,来保证多线程访问共享变量时的可见性、有序性和原子性。(更多内容请参考再有人问你Java内存模型是什么,就把这篇文章发给他。)

内存模型(Memory Model)如果扩展开来说的话,通常指的是内存一致性模型(Memory Sequential Consistency Model)

前面我们提到过缓存一致性,这里又要说内存一致性,不是故意要把读者搞蒙,而是希望通过对比让读者更加清楚。

缓存一致性(Cache Coherence),解决是多个缓存副本之间的数据的一致性问题。

内存一致性(Memory Consistency),保证的是多线程程序访问内存时可以读到什么值。

我们首先看以下程序:

初始:x=0 y=0Thread1:
S1:x=1
L1:r1=yThread2:
S2:y=2
L2:r2=x

其中,S1、S2、L1、L2是语句代号(S表示Store,L表示Load);r1和r2是两个寄存器。x和y是两个不同的内存变量。两个线程执行完之后,r1和r2可能是什么值?

注意到线程是并发、交替执行的,下面是可能的执行顺序和相应结果:

S1 L1 S2 L2 那么r1=0 r2=2S1 S2 L1 L2 那么r1=2 r2=1S2 L2 S1 L1 那么r1=2 r2=0

这些都是意料之内、情理之中的。但是在x86体系结构下,很可能得到r1=0 r2=0这样的结果。

如果没有Memory Consistency,程序员写的程序代码的输出结果是不确定的。

因此,Memory Consistency就是程序员(编程语言)、编译器、CPU间的一种协议。这个协议保证了程序访问内存时会得到什么值。

简单点说,内存一致性,就是保证并发场景下的程序运行结果和程序员预期是一样的(当然,要通过加锁等方式),包括的就是并发编程中的原子性、有序性和可见性。而缓存一致性说的就是并发编程中的可见性。

在很多内存模型的实现中,关于缓存一致性的保证都是通过硬件层面缓存一致性协议来保证的。需要注意的是,这里提到的内存模型,是计算机内存模型,而非Java内存模型。

 

 

总结

缓存一致性问题。硬件层面的问题,指的是由于多核计算机中有多套缓存,各个缓存之间的数据不一致性问题。

PS:这里还需要再重复一遍,Java多线程中,每个线程都有自己的工作内存,需要和主存进行交互。这里的工作内存和计算机硬件的缓存并不是一回事儿,只是可以相互类比。所以,并发编程的可见性问题,是因为各个线程之间的本地内存数据不一致导致的,和计算机缓存并无关系。

缓存一致性协议。用来解决缓存一致性问题的,常用的是MESI协议。

内存一致性模型。屏蔽计算机硬件问题,主要来解决并发编程中的原子性、有序性和一致性问题。

实现内存一致性模型的时候可能会用到缓存一致性模型。

 

 

思考

最后,再给大家留一道思考题:

既然在硬件层面,已经有了缓存一致性协议,可以保证缓存的一致性即并发编程中的可见性,那么为什么在写多线程的代码的时候,程序员要自己使用volatile、synchronized等关键字来保证可见性?

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/324962.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

这是什么操作?java中的变量竟然可以先使用后声明?

相信大家在看到标题之后,是疑惑的点进来看内容的。 在看到标题之后,大家肯定会怀疑,我赵某人用java写了好几年的代码了,还真就没见过java中的变量能先用在声明,今天就是进来看看你在没有声明变量的前提下是怎么用的&a…

重写(override / overwrite)

方法的重写(override / overwrite) 1.重写:子类继承父类以后,可以对父类中同名同参数的方法,进行覆盖操作 2.应用:重写以后,当创建子类对象以后,通过子类对象调用子父类中的同名同参数的方法时,…

ssl1613-最短路径问题【图论,最短路径(还不明显?)】

题目 一个图,求两个点的最短路径 输入 第一行为一个整数n。 n行,两个整数x和y,一个点的坐标 一个整数m,表示图中线的个数。 m行,一条线,i,j,表示第i个点和第j个点之间有线。 最后一行&am…

jQuery 表格实现

<script type"text/javascript">$(function(){/******实现全选的操作****/$("#chks").click(function(){//获得当前框的勾选状态var flag $("#chks").prop("checked");$("input[namechk]").prop(checked,flag);})/*…

来吧学学.Net Core之项目文件简介及配置文件与IOC的使用

序言 在当前编程语言蓬勃发展与竞争的时期,对于我们.net从业者来说,.Net Core是风头正紧,势不可挡的.芸芸口水之中,不学习使用Core,你的圈内处境或许会渐渐的被边缘化.所以我们还是抽出一点点时间学学.net core吧. 那VS Code 可以编写,也可以调试Core本人也尝试啦下,但是感觉…

真正的问题应该在我身上……

渐渐地&#xff0c;学生已进入学习状态。在未测试之前&#xff0c;一直以为大家都学的很好&#xff0c;从课堂上的互动氛围就可以看得出来&#xff0c;一问问题&#xff0c;你一言他一语的……在测试之后&#xff0c;真是让我大跌眼镜&#xff0c;平时感觉表现很好的学生们&…

搞定计算机网络面试,看这篇就够了

转载自 搞定计算机网络面试&#xff0c;看这篇就够了 文章目录结构&#xff1a; 一 OSI与TCP/IP各层的结构与功能&#xff0c;都有哪些协议 运输层主要使用以下两种协议&#xff1a; UDP的主要特点&#xff1a; TCP的主要特点&#xff1a; 域名系统&#xff08;Domain Nam…

来吧学学.Net Core之登录认证与跨域资源使用

序言 学习core登录认证与跨域资源共享是越不过的砍,所以我在学习中同样也遇到啦这两个问题,今天我们就用示例来演示下使用下这2个技术点吧. 本篇主要内容如下: 1、展示一个登录认证的简单示例 2、跨域资源访问 3、跨域获取登录认证的用户信息 .Net Core使用身份认证(Auth…

ssl1760-商店选址问题【图论,最短路】

题目 给出一个城市的地图&#xff08;用邻接矩阵表示&#xff09;&#xff0c;商店设在一点&#xff0c;使各个地方到商店距离之和最短。 输入 第一行为n&#xff08;共有几个城市&#xff09;&#xff1b; N小于201 之后邻接矩阵 3 0 3 1 3 0 2 1 2 0 输出 最短路径…

JSP 获得服务器时间和浏览器时间

发布项目到服务器并访问 创建Web项目&#xff0c;开发静态页面 部署到服务器Tomcat 启动服务器Tomcat 不同用户通过浏览器来访问Web项目 Web项目和Java项目的区别 Web项目需要JavaEE的类库 Web项目中还可以存放静态网页和动态网页 开发目录和部署目录的区别 开发目录&…

如果要你选择某读书APP的图标,你会选择哪一个?

声明&#xff1a;介于尊重每位同学的劳动成果&#xff0c;故本文所有广告收入、赞赏均会均分给同学们&#xff01;最近学到了平面设计基础&#xff0c;于是让同学们用所学知识以“读书”为主题&#xff0c;原创了各式各样的图标&#xff0c;也许屏幕前的你只是轻轻的一划而过&a…

从理论知识到落地能力,你欠缺了什么?

转载自 从理论知识到落地能力&#xff0c;你欠缺了什么&#xff1f; 本文是一个理论过度到实践的典型案例&#xff0c;借助程序员经常遇到的一个问题——网络为什么不通&#xff0c;来具体说明怎么将书本上的死知识真正变成我们解决问题的能力。 大学学到的基本概念 我相信…

三大特性之多态性

1.理解多态性&#xff1a;可以理解为一个事物的多种形态。 2.何为多态性&#xff1a; 对象的多态性&#xff1a;父类的引用指向子类的对象&#xff08;或子类的对象赋给父类的引用&#xff09; 3.多态的使用&#xff1a;虚拟方法调用 有了对象的多态性以后&#xff0c;我们在编…

在这里,我们为您绘制了专属海报,请您查收!

树叶在空中飘荡&#xff0c;谱写着一曲感恩的乐章&#xff0c;那是大树对滋养它的大地的感恩;白云在蔚蓝的天空中飘荡&#xff0c;绘画着那一幅幅感人的画面&#xff0c;那是白云对哺育它的蓝天的感恩。我们沐浴着爱的阳光长大&#xff0c;我们滋润着人间的真情成长&#xff0c…

ssl1761-城市问题【图论,最短路,Dijkstra】

题目 一个图&#xff0c;输出从k点到每个点的最短路 输入 第一行有两个整数n和k&#xff0c;中间用空格隔开&#xff1b;以下是一个NxN的矩阵&#xff0c;表示点间的距离。 3 1 0 3 1 3 0 2 1 2 0 输出 输出点k到各点的距离 3 0 2 解题思路 用Dijkstra算法&#xff…

10分钟就能学会的.NET Core配置

.NET Core为我们提供了一套用于配置的API&#xff0c;它为程序提供了运行时从文件、命令行参数、环境变量等读取配置的方法。配置都是键值对的形式&#xff0c;并且支持嵌套&#xff0c;.NET Core还内建了从配置反序列化为POCO对象的支持。 目前支持以下配置Provider&#xff…

String 使用不当可能导致内存泄露

转载自 String 使用不当可能导致内存泄露 String是Java中一个比较基础的类&#xff0c;每一个开发人员都会经常接触到。而且&#xff0c;String也是面试中经常会考的知识点。String有很多方法&#xff0c;有些方法比较常用&#xff0c;有些方法不太常用。 今天介绍一个Strin…

instanceof关键字

instanceof关键字的使用 a instanceof A:判断对象a是否是类A的实例。如果是&#xff0c;返回true&#xff1b;如果不是&#xff0c;返回false。 使用情境&#xff1a;为了避免在向下转型时出现ClassCastException的异常&#xff0c;我们在向下转型之前&#xff0c;先 进行ins…

王宝兴同学谈学习!

对于学习&#xff0c;我认为心态很重要。只要我们明白就应做什么&#xff0c;此刻需要做什么&#xff0c;才能不断地向前迈进&#xff0c;直至终点。不要怕累。其实谁都一样&#xff0c;学习很累&#xff0c;可这个累只是暂时的。只要坚持下去&#xff0c;努力下去&#xff0c;…

ssl1614-医院设置【图论,最短路】

题目 一个像树一样的无向图&#xff0c;每个点有个值&#xff0c;每条边权值都是1&#xff0c;然后 若医院建在&#xff1a;   1处&#xff0c;则距离和4122*202*40136   3处&#xff0c;则距离和4*213204081 要求距离和最小 输入 第一行一个整数n&#xff0c;表示…