2021-05-10

Java多线程系列(2)

缓存一致性协议(MESI)

为什么要使用MESI协议?


多线程下存在的问题

在多处理器系统中,每个处理器都有自己的高速缓存,而它们又共享同一主内(MainMemory)。基于高速缓存的存储交互很好地解决了处理器与内存的速度矛盾,但是也引入了新的问题:缓存一致性(CacheCoherence)。当多个处理器的运算任务都涉及同一块主内存区域时,将可能导致各自的缓存数据不一致的情况,如果真的发生这种情况,那同步回到主内存时以谁的缓存数据为准呢?为了解决一致性的问题,需要各个处理器访问缓存时都遵循一些协议,在读写时要根据协议来进行操作,这类协议有MSI、MESI(IllinoisProtocol)、MOSI、Synapse、Firefly DragonProtocol,等等。
 

缓存一致性协议(MESI)

官方定义:MESI协议是基于Invalidate的高速缓存一致性协议,并且是支持回写高速缓存的最常用协议之一。 

个人理解:说白了就是为了保证主内存和多核CPU或者多CPU里面的缓存的数据在同一时刻都保持一致。如果是单CPU的单核的的就不需要使用缓存一致性协议,因为始终就一个CPU去访问数据不存在不一致的问题。

为什么要使用MESI协议?

首先我们来看一个场景:如下图所示

如上图所示,当两个线程T1属于CPU1,T2属于CPU2同时访问主内存中的共享变量X=5时,首先回去各自的缓存中去找,如果缓存中不存在就去主内存中去找。

然后T1执行了一次加法运算,此时X的值变为6,然后此时T2也执行了一次加法,按道理来说此时X的值应该为7,但是实际情况下在CPU2的缓存中的值依然是X等于6.也就是说CPU2并没有嗅探到CPU1对变量X=5进行了一次加法运算,而是按照自己缓存中存在的数进行了加1运算。假如CPU1立马把值刷回到主内存中,但是对于CPU2来说他依然的结果是6?为啥呢?因为一开始他们两个同时把X=5加载到了自己的缓存中去了,所以首先去缓存中找,如果缓存中存在就直接加载到寄存器里了不在去主内存找了,然后计算结果是6,刷到缓存中。

从上面的问题我们可以看出在多CPU或者多核CPU中存在主内存和各个缓存的数据不一致的问题?为了解决这个问题,提出了两种办法一是:总线加锁,二是:使用MESI协议(在这里我们之论述MESI)。如下图所示:

其中缓存行是缓存中的最小存储单元,里面存储的是从主内存中加载的共享变量。

缓存一致性协议主要包括缓存行的的四种状态:

M: 被修改(Modified)

该缓存行只缓存在该CPU的缓存中,并且是被修改过的(dirty),即与主存中的数据不一致,该缓存行中的共享变量需要在未来的某个时间点写回(write back)主存。当被写回主存之后,该缓存行的状态会变成独享(exclusive)状态。

E: 独享的(Exclusive)

该缓存行只被缓存在该CPU的缓存中,它是未被修改过的(clean),与主存中数据一致。该状态可以在任何时刻变成共享状态(shared),比如当其它CPU读取内存中的值时。同样地,当该CPU修改该缓存行中内容时,该状态可以变成Modified状态。

S: 共享的(Shared)

该状态意味着该缓存行中的共享变量可能被多个CPU缓存,并且各个缓存中的数据与主存数据一致(clean),当有一个CPU修改自己缓存行中的内容时中,其它CPU中的缓存行中的共享变量可以被作废(变成无效状态(Invalid))。

I: 无效的(Invalid)

该缓存是无效的(可能有其它CPU修改了该缓存行)。

每个CPU都会时刻监听总线,都会时刻监听到这个共享变量在某一时刻处于哪个状态,以便对自己缓存中的共享变量进行更新或者其它操作。

操作:

一个写请求只有在该CPU的缓存行是M或者E状态时才能被执行,如果缓存行处于S状态,必须先将其它缓存中该缓存行变成Invalid状态(也既是不允许不同CPU同时修改同一缓存行,即使修改该缓存行中不同位置的数据也不允许)。该操作经常作用广播的方式来完成,例如:Request For Ownership (RFO)

所有的状态转换如下所示:

一个处于S状态的缓存行也必须监听其它缓存,当其它缓存行的内容被修改时,立刻把自己的缓存行变成无效(Invalid)。

一个处于E(就说明他修改了,然后把值刷回到了主内存中,此时它和主内存中的数据是一致的)状态的缓存行也必须监听其它缓存,所以当其它缓存读主存中的值时,一旦有这种操作,该缓存行需要变成S状态。

一个处于M状态的缓存行也必须时刻监听总线,M(Modified)和E(Exclusive)状态的缓存行,数据是独有的,不同点在于M状态的数据是dirty的(和内存的不一致),E状态的数据是clean的(和内存的一致)。

M状态和I状态示例如下:

 Core 0修改了x的值之后,这个Cache line变成了M(Modified)状态,其他Core对应的Cache line变成了I(Invalid)状态。

在MESI协议中,每个Cache的Cache控制器不仅知道自己的读写操作,而且也监听(snoop)其它Cache的读写操作。每个Cache line所处的状态根据本核和其它核的读写操作在4个状态间进行迁移。

参考:https://blog.csdn.net/muxiqingyang/article/details/6615199?utm_medium=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.vipsorttest&depth_1-utm_source=distribute.pc_relevant.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-3.vipsorttest

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
这个数据可以使用Python进行解析和处理。可以按照以下步骤进行: 1. 将数据分割成每个数据项。 ``` data_items = data.split(',') ``` 2. 对于每个数据项,将其按#分割成四个小项,并存储到一个列表中。 ``` data_list = [] for item in data_items: item_list = item.split('#') data_list.append(item_list) ``` 3. 对于每个小项,进行相应的类型转换。 ``` for item in data_list: item[0] = int(item[0]) # 题号转换为整数 item[1] = datetime.datetime.strptime(item[1], '%Y-%m-%d %H:%M:%S') # 时间转换为datetime类型 if item[2] != '': # 操作类型转换为整数 item[2] = int(item[2]) item[3] = str(item[3]) # 科目转换为字符串类型 ``` 4. 可以按照需要对数据进行进一步处理,如按照题号、时间等进行排序、筛选等操作。 完整的Python代码如下: ``` import datetime data = '''1#2021-05-18 14:31:55##初级会计实务,2#2021-05-18 14:31:57#12#初级会计实务,2#2021-05-18 14:32:08##初级会计实务,3#2021-05-18 14:32:09#12#初级会计实务,4#2021-05-18 14:32:34#12#初级会计实务,4#2021-05-18 14:32:45##初级会计实务,5#2021-05-18 14:32:46#12#初级会计实务,5#2021-05-18 14:32:57##初级会计实务,6#2021-05-18 14:33:00#12#初级会计实务,7#2021-05-18 14:33:44#12#初级会计实务,7#2021-05-18 14:34:42##初级会计实务,8#2021-05-18 14:34:43#12''' # 将数据分割成每个数据项 data_items = data.split(',') # 对于每个数据项,将其按#分割成四个小项,并存储到一个列表中 data_list = [] for item in data_items: item_list = item.split('#') data_list.append(item_list) # 对于每个小项,进行相应的类型转换 for item in data_list: item[0] = int(item[0]) # 题号转换为整数 item[1] = datetime.datetime.strptime(item[1], '%Y-%m-%d %H:%M:%S') # 时间转换为datetime类型 if item[2] != '': # 操作类型转换为整数 item[2] = int(item[2]) item[3] = str(item[3]) # 科目转换为字符串类型 print(data_list) ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值