精华内容
下载资源
问答
  • MESI缓存一致性

    2019-05-05 14:44:25
    CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部原理。 时间局部(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。 比如...

    CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。

    时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。

    比如循环、递归、方法的反复调用等。

    空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。

    比如顺序执行的代码、连续创建的两个对象、数组等。

    带有高速缓存的CPU执行计算的流程

    程序以及数据被加载到主内存

    指令和数据被加载到CPU的高速缓存

    CPU执行指令,把结果写到高速缓存

    高速缓存中的数据写回主内存
    在这里插入图片描述

    MESI

    多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个一致性的协议MESI。
    MESI 是指4中状态的首字母。每个Cache line有4个状态,可用2个bit表示,它们分别是:

    缓存行(Cache line):缓存存储数据的单元。
    在这里插入图片描述
    注意:
    对于M和E状态而言总是精确的,他们在和该缓存行的真正状态是一致的,而S状态可能是非一致的。如果一个缓存将处于S状态的缓存行作废了,而另一个缓存实际上可能已经独享了该缓存行,但是该缓存却不会将该缓存行升迁为E状态,这是因为其它缓存不会广播他们作废掉该缓存行的通知,同样由于缓存并没有保存该缓存行的copy的数量,因此(即使有这种通知)也没有办法确定自己是否已经独享了该缓存行。

    从上面的意义看来E状态是一种投机性的优化:如果一个CPU想修改一个处于S状态的缓存行,总线事务需要将所有该缓存行的copy变成invalid状态,而修改E状态的缓存不需要使用总线事务。

    状态变化

    有三个CPU A、B、C,对应三个缓存分别是cache a、b、 c。在主内存中定义了x的引用值为0。
    在这里插入图片描述
    1.单核读取

    那么执行流程是:
    CPU A发出了一条指令,从主内存中读取x。
    从主内存通过bus读取到缓存中(远端读取Remote read),这是该Cache line修改为E状态(独享).
    在这里插入图片描述

    2.双核读取

    那么执行流程是:
    CPU A发出了一条指令,从主内存中读取x。
    CPU A从主内存通过bus读取到 cache a中并将该cache line 设置为E状态。
    CPU B发出了一条指令,从主内存中读取x。
    CPU B试图从主内存中读取x时,CPU A检测到了地址冲突。这时CPU A对相关数据做出响应。此时x 存储于cache a和cache b中,x在chche a和cache b中都被设置为S状态(共享)。
    在这里插入图片描述
    3.修改数据

    那么执行流程是:
    CPU A 计算完成后发指令需要修改x.
    CPU A 将x设置为M状态(修改)并通知缓存了x的CPU B, CPU B将本地cache b中的x设置为I状态(无效)
    CPU A 对x进行赋值。
    在这里插入图片描述
    4.同步数据

    那么执行流程是:

    CPU B 发出了要读取x的指令。
    CPU B 通知CPU A,CPU A将修改后的数据同步到主内存时cache a 修改为E(独享)
    CPU A同步CPU B的x,将cache a和同步后cache b中的x设置为S状态(共享)。
    在这里插入图片描述

    MESI优化和他们引入的问题

    缓存的一致性消息传递是要时间的,这就使其切换时会产生延迟。当一个缓存被切换状态时其他缓存收到消息完成各自的切换并且发出回应消息这么一长串的时间中CPU都会等待所有缓存响应完成。可能出现的阻塞都会导致各种各样的性能问题和稳定性问题。

    CPU切换状态阻塞解决-存储缓存(Store Bufferes)

    比如你需要修改本地缓存中的一条信息,那么你必须将I(无效)状态通知到其他拥有该缓存数据的CPU缓存中,并且等待确认。等待确认的过程会阻塞处理器,这会降低处理器的性能。因为这个等待远远比一个指令的执行时间长的多。

    为了避免这种CPU运算能力的浪费,Store Bufferes被引入使用。处理器把它想要写入到主存的值写到缓存,然后继续去处理其他事情。当所有失效确认(Invalidate Acknowledge)都接收到时,数据才会最终被提交。

    这么做有两个风险
    第一、就是处理器会尝试从存储缓存(Store buffer)中读取值,但它还没有进行提交。这个的解决方案称为Store Forwarding,它使得加载的时候,如果存储缓存中存在,则进行返回。

    第二、保存什么时候会完成,这个并没有任何保证。

    value = 3;

    void exeToCPUA(){
    value = 10;
    isFinsh = true;
    }
    void exeToCPUB(){
    if(isFinsh){
    //value一定等于10?!
    assert value == 10;
    }
    }
    试想一下开始执行时,CPU A保存着finished在E(独享)状态,而value并没有保存在它的缓存中。(例如,Invalid)。在这种情况下,value会比finished更迟地抛弃存储缓存。完全有可能CPU B读取finished的值为true,而value的值不等于10。

    即isFinsh的赋值在value赋值之前。

    这种在可识别的行为中发生的变化称为重排序(reordings)。注意,这不意味着你的指令的位置被恶意(或者好意)地更改。

    它只是意味着其他的CPU会读到跟程序中写入的顺序不一样的结果。

    顺便提一下NIO的设计和Store Bufferes的设计是非常相像的。

    硬件内存模型

    执行失效也不是一个简单的操作,它需要处理器去处理。另外,存储缓存(Store Buffers)并不是无穷大的,所以处理器有时需要等待失效确认的返回。这两个操作都会使得性能大幅降低。为了应付这种情况,引入了失效队列。它们的约定如下:

    对于所有的收到的Invalidate请求,Invalidate Acknowlege消息必须立刻发送
    Invalidate并不真正执行,而是被放在一个特殊的队列中,在方便的时候才会去执行。
    处理器不会发送任何消息给所处理的缓存条目,直到它处理Invalidate。
    即便是这样处理器已然不知道什么时候优化是允许的,而什么时候并不允许。

    干脆处理器将这个任务丢给了写代码的人。这就是内存屏障(Memory Barriers)。

    写屏障 Store Memory Barrier(a.k.a. ST, SMB, smp_wmb)是一条告诉处理器在执行这之后的指令之前,应用所有已经在存储缓存(store buffer)中的保存的指令。

    读屏障Load Memory Barrier (a.k.a. LD, RMB, smp_rmb)是一条告诉处理器在执行任何的加载前,先应用所有已经在失效队列中的失效操作的指令。

    void executedOnCpu0() {
    value = 10;
    //在更新数据之前必须将所有存储缓存(store buffer)中的指令执行完毕。
    storeMemoryBarrier();
    finished = true;
    }
    void executedOnCpu1() {
    while(!finished);
    //在读取之前将所有失效队列中关于该数据的指令执行完毕。
    loadMemoryBarrier();
    assert value == 10;
    }

    转载https://blog.csdn.net/m18870420619/article/details/82431319

    展开全文
  • 白话CPU MESI缓存一致性协议CPU缓存L1缓存/L2缓存/L3缓存cache line缓存条目(cache line)近一步可以分为三个部分:MSEI总结 CPU缓存 想要了解 CPU MESI缓存一致性协议 首先需要了解什么是CPU缓存。说CPU缓存之前,...

    CPU缓存

    想要了解 CPU MESI缓存一致性协议 首先需要了解什么是CPU缓存。说CPU缓存之前,先了解一下CPU执行过程,但是CPU执行指令的过程非常复杂,这里我就直接简化为从内存中加载指令、执行指令、获取内存数据、将执行结果回写回内存。

    CPU执行指令的速度是非常快,但是在获取内存数据的话会有很长时间的延时(下图可知在120ns左右),这对于执行指令来说是完全不能接受的,所以就出现了CPU缓存这个东西,CPU缓存是直接集成在CPU中,离CPU最近,所以CPU在获取数据的时候不会直接去内存中获取,而是先从CPU缓存中获取,不需要通过地址总线(就是主板上的一个通道)去内存中去获取,从而提升了程序执行效率,采取了就近的原则。其实根本原因就是CPU运算速度与内存读写速度不匹配导致,这也和我们业务中的Redis类似,读取数据库非常慢,但是读Redis非常快,所以获取数据先从Redis中获取,如果没有再去数据库中读,以加快程序响应速度。其实也给我们一思维就是要是觉得程序执行慢,加缓存就完了(但是加缓冲也会产生各种各样的问题)。

    在这里插入图片描述

    L1缓存/L2缓存/L3缓存

    上面我们已经知道了CPU缓存这个东西,但是上面图中的L1缓存/L2缓存/L3缓存又是什么,非常简单L1缓存/L2缓存/L3缓存其实统称叫做CPU缓存,只不过分了三级,L1最靠近CPU核心,L2其次,L3再次,运行速度方面:L1最快、L2次快、L3最慢;容量大小方面:L1最小、L2较大、L3最大。CPU会先在最快的L1中寻找需要的数据,找不到再去找次快的L2,还找不到再去找L3,L3都没有那就只能去内存找了。
    在这里插入图片描述
    看到这个图片之后我第一想法就是我们在分布式的系统看到的图片真是太像了,所以我想在这样一个类似分布式的框架中我们能从中的到什么有价值的东西,就需要我和大家思考了。

    cache line

    怎么说着说着就突然就提到了这个不搭噶的名词cache line,这就要从CPU缓存的结构开始说起,从网上找了一个理解起来比较清晰的图片。在这里插入图片描述
    CPU中的高速缓存内部结构是一个拉链散列表,和HashMap的底层结构以及原理十分相似。它分为若干桶,每个桶是一个链表,包含若干缓存条目,每个缓存条目就是一个cache line。一个cache line一般是64 bytes,假设程序中读取某一个int变量,CPU并不是只从主存中读取4个字节,而是会一次性读取64个字节,然后放到cpu cache中。因为往往紧挨着的数据,更有可能在接下来会被使用到。比如遍历一个数组,因为数组空间是连续的,所以并不是每次取数组中的元素都要从主存中去拿,第一次从主存把数据放到cache line中,后续访问的数据很有可能已经在cache中了。(有点类似IO的时候,在进行磁盘读取的时候会把相邻的数据也读取到,也是类似的考虑吧)

    再来看一下这句话是不是就很好理解了呢:

    在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部性原理。
    时间局部性(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。比如循环、递归、方法的反复调用等。
    空间局部性(Spatial Locality):如果一个存储器的位置被引用,那么将来他附近的位置也会被引用。比如顺序执行的代码、连续创建的两个对象、数组等。

    缓存条目(cache line)近一步可以分为三个部分:

    在这里插入图片描述
    CPU访问内存时,会通过内存地址解码的三个数据:index(桶编号)、tag(缓存条目的相对编号)、offset(变量在缓存条目中的位置偏移)来获取高速缓存中对应的数据。

    这时候可以看到Flag这个标识了,然后就可以引出了状态值的概念,然后就可以引出我们所说的MSEI协议了。

    MSEI缓存一致性协议

    MSEI其实就是四种状态首字母的简写,就代表上面缓存条目(cache line)的四种状态,分别是:

    状态描述
    M 修改 (Modified)该Cache line有效,数据被修改了,和内存中的数据不一致,数据只存在于本Cache中。
    E 独享、互斥 (Exclusive)该Cache line有效,数据和内存中的数据一致,数据只存在于本Cache中。
    S 共享 (Shared)该Cache line有效,数据和内存中的数据一致,数据存在于很多Cache中。
    I 无效 (Invalid)该Cache line无效。

    我觉得文字还是表达的有点苍白直接上图吧:

    E状态示例如下:

    在这里插入图片描述
    只有Core 0访问变量x,它的Cache line状态为E(Exclusive)。

    S状态示例如下:
    在这里插入图片描述
    3个Core都访问变量x,它们对应的Cache line为S(Shared)状态。

    M状态和I状态示例如下:
    在这里插入图片描述
    Core 0修改了x的值之后,这个Cache line变成了M(Modified)状态,其他Core对应的Cache line变成了I(Invalid)状态。

    在MESI协议中,每个Cache的Cache控制器不仅知道自己的读写操作,而且也监听(snoop)其它Cache的读写操作。每个Cache line所处的状态根据本核和其它核的读写操作在4个状态间进行迁移。
    在这里插入图片描述
    其实我是不想贴这张图的,因为看起来实在是太恶心了,我觉得文字描述起来会简单一点。

    既然知道了cache line有四种状态,那么必然会有某个操作会去触发状态的改变,这个某个操作就是:

    1. Local Read表示本内核读本Cache中的值
    2. Local Write表示本内核写本Cache中的值
    3. Remote Read表示其它内核读其它内核Cache中的值
    4. Remote Write表示其它内核写其它内核Cache中的值

    一共有四种状态,四种状态下还对应四种操作,那么就有十六种情况,不要慌,虽然说有十六种但是有的状态下的操作是没有意义的,所以会少很多,而且很容易理解,耐心看一定会恍然大悟的。

    现在cache line是I(Invalid)状态,看上面的图可知,此时有其他核在修改S(shared)状态下的共享变量,修改的那个核是M(modified)状态,其他核里面的变量状态就是I(Invalid)状态,当前CPU中是脏数据,不可用,其他CPU可能有数据、也可能没有数据;

    操作描述
    Local Read如果其他Cache没有这份数据,本Cache从内存中取数据,cache line状态变为E
    Local Read如果其他核的Cache有这份数据,且状态为M,此核等待其他核将数据刷新到内存后,此核再从内存中读取数据刷新到此核的缓存中,两个核的cache line状态都变为S
    Local Read如果其他核的Cache有这份数据,且状态为S或者E,本Cache从内存中取数据,这些cache line状态变为S
    Local Write因为此核的数据是无效的所以需要从内存中取数据,然后修改自己cache line中的数据,再将状态设置为M(因为发生了修改)
    Local Write如果其他Cache有这份数据,且状态为M,此核等待其他核将数据刷新到内存,并将其他核的cache line状态设置为I后,此核再从内存中读取数据刷新到此核的缓存中,修改自己核中的cache line为M
    Local Write如果其他Cache有这份数据,且状态为S或者E,本核Cache直接修改自己的cache line数据并将状态设置为M,告诉其他核的Cache将他们的cache line设置为I(从而保证自己有效但是其他核是无效的)
    Remote Write我自己都已经是Invalid状态了,别的核怎么操作都与我不搭噶
    Remote Read我自己都已经是Invalid状态了,别的核怎么操作都与我不搭噶

    现在cache line是E(Exclusive)状态,看上面的图可知,只有此核的cache line含有内存的副本变量

    操作描述
    Local Read只是自己核读取自己核的数据,状态不变
    Local Write只是自己核修改了自己核的数据,但是状态要修改为M
    Remote Write说明其他核修改了同样的数据,那么为了保证数据不能够被脏读,就需要让这个核的数据无效,需要读的话重新去内存中或其他核中去读,所以这个核的cache line设置为I
    Remote Read说明其他核也读取了同样的数据,那么这个核就是共享了数据,状态设置为S

    现在cache line是S(Shared)状态,看上面的图可知,多个核存在此cache line的内存副本

    操作描述
    Local Read这个核读取这个核自己的数据,与其他核不搭噶,所以状态不变
    Local Write这个核修改这个核的数据,首先需要将自己的状态设置为M,同时需要告诉其他核他们的数据已经是过期的数据了,需要设置为I状态
    Remote Write其他核修改了其他核的数据,可以换位思考一下,其实就是其他核发生了其他核的Local Write,当然相对于其他核,这个核就是其他核,所以这个核需要设置为I状态,说明自己的数据已经是过期的数据了
    Remote Read其他核读取其他核的数据,与自己不搭噶,所以状态不变

    现在cache line是M(Modified)状态,看上面的图可知,当前核正在修改数据,这个核的数据是最新的,所有的数据都以当前核的数据为准

    操作描述
    Local Read这个核读取这个核自己的数据,与其他核不搭噶,这个核已经是最新的数据了,所以状态不变
    Local Write这个核修改这个核自己的数据,与其他核不搭噶,这个核已经是最新的数据了,修改后数据还是最新的,所以状态不变
    Remote Write其他核需要修改其他核中同样的数据,但是其他核中不是最新的,所以需要从内存中读取,为了保证一致性,这个核首先会将自己最新的数据写到内存中,其他核就和当前这个核拥有了同样的最新数据,然后会将状态设置为I,因为其他核中的数据现在是最新的了,现在自己核的数据是过期的数据
    Remote Read其他核需要读取其他核中同样的数据,但是其他核中不是最新的,所以需要从内存中读取,为了保证一致性,这个核首先会将自己最新的数据写到内存中,其他核就和当前这个核拥有了同样的最新数据,然后会将状态设置为S,因为多个核共享了一个数据

    总结

    MESI协议为了保证多个CPU cache中共享数据的一致性,定义了cache line的四种状态,而CPU对cache的4种操作可能会产生不一致状态,因此cache控制器监听到本地操作和远程操作的时候,需要对地址一致的cache line状态做出一定的修改,从而保证数据在多个cache之间流转的一致性。

    总感觉这种设计方式在实际的应用场景下作用不太大,感觉一个cache line需要不停的去监听其他cache line的状态,而且还需去等其他的状态改变完了才进行下面的操作。但是这个通过状态和监听的方式保证一致性还是值得学习的。

    展开全文
  • MESI缓存一致性协议

    2021-07-10 22:12:24
    1. MESI缓存一致性协议 现代处理器的缓存一般分为三级,由每一个核心独享的L1、L2 Cache,以及所有的核心共享L3 Cache组成,具体每个cache,实际上是有很多缓存行组成: 缓存一致性协议给缓存行(通常为64字节)...

    来源:https://www.bilibili.com/video/BV1Rv411y7MU?from=search&seid=9769842728262062596

    1. MESI缓存一致性协议

    现代处理器的缓存一般分为三级,由每一个核心独享的L1、L2 Cache,以及所有的核心共享L3 Cache组成,具体每个cache,实际上是有很多缓存行组成:

    img

    缓存一致性协议给缓存行(通常为64字节)定义了个状态:独占(exclusive)、共享(share)、修改 (modified)、失效(invalid),用来描述该缓存行是否被多处理器共享、是否修改。所以缓存一致性协议也称 MESI协议。

    • 独占(exclusive):仅当前处理器拥有该缓存行,并且没有修改过,是最新的值。

    • 共享(share):有多个处理器拥有该缓存行,每个处理器都没有修改过缓存,是最新的值。

    • 修改(modified):仅当前处理器拥有该缓存行,并且缓存行被修改过了,一定时间内会写回主存,会写成功状态会变为S。

    • 失效(invalid):缓存行被其他处理器修改过,该值不是最新的值,需要读取主存上最新的值。

    协议协作如下:

    • 一个处于M状态的缓存行,`必须时刻监所有试图读取该缓存行对应的主存地址的操作,如果监听到,则必须在此操作执行前把其缓存行中的数据写回CPU。

    • 一个处于S状态的缓存行,必须时刻监听使该缓存行无效或者独享该缓存行的请求,如果监听到,则必须把其缓存行状态设置为I。

    • 一个处于E状态的缓存行,必须时刻监听其他试图读取该缓存行对应的主存地址的操作,如果监听到,则必须把其缓存行状态设置为S。

    • 当CPU需要读取数据时,如果其缓存行的状态是I的,则需要从内存中读取并把自己状态变成S,如果不是I,则可以直接读取缓存中的值,但在此之前,必须要等待其他CPU的监听结果,如其他CPU有该数据的缓存且状态是M,则需要等待其把缓存更新到内存之后,再读取。

    • 当CPU需要写数据时,只有在其缓存行是M或者E的时候才能执行,否则需要发出特殊的RFO指令(Read Or Ownership,这是一种总线事务),通知其他CPU置缓存无效(I),这种情况下会性能开销是相对较大的。在写入完成后,修改其缓存状态为M。

    展开全文
  • CPU通过MESI缓存一致性协议来保证缓存之间的协同工作

    M(Modify)表示缓存行中的数据已经修改了,和主内存不一致,此时会阻止其他读取主内存对应数据的操作

    E(Exclusive)表示缓存行中的数据被当前缓存独占,其他缓存没有缓存此缓存行的数据,此时会监听其他缓存操作该缓存行对应在内存中的数据,如果有,那都将改为S

    S(Share)表示共享状态,就是该缓存行的内容也被缓存在其他缓存中,  此时会监听其他缓存是否有将该缓存行设置为M修改或者E独占的状态,如果有,那将改为I

    I(Invalid) 表示失效状态

    接下来就根据这四种状态的相互切换来讲一下缓存之间的协同流程

    首先Core A读取主存中的A数据放进缓存行中,此时这个缓存行会变成E状态

    接着,CoreB读取主存中的A数据放进缓存行中,CoreA检测到该缓存行的数据也被其他缓存缓存了,于是将存放了A缓存行改为S共享状态,Core读取时也检测到,于是也设置为S共享状态

    此时CoreA打算修改数据A,将其设置E修改状态,CoreB检测到,于是将缓存了A数据的缓存行设置为I无效状态,完成后,Core A再将数据A进行修改

    最后CoreB打算读取数据A 了,于是CoreA监听到并将数据A同步到主内存中,并将数据A修改为E状态,于是数据B就可以读取主内内的数据A了,CoreA监听到了,于是就改回了S状态,CoreB也设置为S状态,这就又回到了一开始共享的状态了.

     

     

     

     

    展开全文
  • 1.1 为什么需要MESI缓存一致性协议 CPU与主存的交互速度差异导致需要多级缓存(L1、L2、L3),缓存的存在会带来的问题就是一致性问题。很早之前采用的锁总线,也就是说除读之外的操作需要锁住总线,但是锁总线的...
  • 文章目录系列文章目录前言一、MESI缓存一致性协议二、MESI协议怎么保证数据一致性的呢?三、cpu是怎么更新这4种状态的呢?总结 前言 上篇文章《多核cpu怎么保证数据一致性(二)cpu为什么要用高速缓存?L1,L2,L3 ...
  • MESI缓存一致性协议 多核CPU多级缓存一致性协议MESI 多核CPU的情况下有多个一级缓存,如何保证缓存内部数据的一致,不让系统数据混乱。这里就引出了一个一致性的协议MESI。 MESI协议缓存状态 MESI 是指4中...
  • 【Java锁体系】八、MESI缓存一致性协议讲解 MESI是一种广泛使用的写回策略的缓存一致性协议。 8.1 MESI协议中的状态 M:Modified被修改 E:Exclusive独享的 S:Shared共享的 I:Invalid无效的 M: 被修改...
  • volatile与MESI缓存一致性协议volatile实例多级缓存结构总线锁多核CPU多级缓存一致性协议MESIMESI协议缓存状态MESI状态转换MESI状态切换举例MESI优化和引入的问题CPU切换状态阻塞解决­存储缓存(Store Bufferes)...
  • 本节将介绍一下计算机的多级缓存(L1、L2、L3)架构、多级缓存与主存怎么进行数据交互的,另外会对MESI缓存一致性协议)做下介绍,为后面的JMM模型、volatile关键字的学习打下基础。 一,现代计算机硬件基本结构 ...
  • 现在的做法使用缓存一致性协议MESI Modified, Exclusive, Shared, Invalid 如下图: T0 通过总线向主内存获取一个缓存行, 该缓存行包含变量counter=0,并加载到Core0的缓存中,这个时候会通过总线对该缓存行...
  • MESI 缓存一致性协议

    2021-06-22 23:20:20
    待完善
  • CAS指令与MESI缓存一致性协议、 “轻量级锁” 与原子操作 “最轻量级的锁”,通常也叫”原子操作”,之所以加引号是因为他们在汇编级别并不是原子操作,是用多条指令完成的,这些操作大多都是利用CPU支持的汇编指令. ...
  • 在CPU访问存储设备时,无论是存取数据抑或存取指令,都趋于聚集在一片连续的区域中,这就被称为局部原理。 时间局部(Temporal Locality):如果一个信息项正在被访问,那么在近期它很可能还会被再次访问。 ...
  • Exclusive, Shared, Invalid).The protocol is named after the four states a cache line can be in when using the MESI protocol: 这导致了 MESI 缓存一致性协议(修改的、独占的、共享的、无效的)的出现。...
  • ①M:modified--与主存的内容相比,有改动就标记为M。我改过,那么对于别人来说就是i了。 ②E:exclusive--内容为我锁独占,标记为E。 ③S:shared--与此同时别人也在读,标记为S。 ④I:invalid--读时被其他CPU...
  • volatile作用——可见 大家都应该知道 volatile 的主要作用有两点: 1、保证变量的内存可见 ;2、禁止指令重排序,今天我们重点来谈谈可见。 首先,在理解 volatile 可见前,先来看一看一个多线程访问...
  • 这个数他会被load到 L3缓存上,L1和L2是在CPU的内部的,这时候会产生一个情况,L3或者主存里面这个数会被load不同的cpu的内部,这个时候如果把cpu1的x修改成1,cpu2的x修改成2,就会产生数据不一致问题,多核同时...
  • 之前说了volatile可以解决线程之间可见性问题 它到底是怎么解决的呢 它底层就利用到了 cpu系统指令的lock(前缀)触发缓存一致性协议 这就涉及到jvm跟硬件交互 首先当我们执行java代码 会加载到元空间 然后在堆中创建...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 6,805
精华内容 2,722
关键字:

mesi缓存一致性