本文来自微信公众号:编程技术宇宙 (ID:xuanyuancoding),作者:轩辕之风

i++ 问题

“阿 Q 赶快回去吧,隔壁二号车间的虎子说我们自己改了的人的数据,上门来闹事了”

时候老 K 的突然出现,我不得不提前结束与小黑的交流,赶回了 CPU 一号车间。

看过我这边,虎子立刻朝我嚷嚷:“的人是为啥回事?才几纳秒的时间,就把数据给我改了,如果我事上为啥办吧!”

我听着迷迷糊糊的,连连谈到:“虎子你先别急,我刚这边,相当出想做什么样样事儿了,先让我了解清楚好不好?”

一会儿,老 K 把这件的经过告诉了我。原来,我们自己一个 CPU 车间各自负责的线程也都执行自己 i++ 的操作方式,我们自己都把 i 的值放到了的人的缓存中,完了自己都都没通知对方,加了两次但结果却只有一次,出现了数据不一致问题。

原子操作方式

了解清楚这件的原委自己,我向虎子说道:“大家都执行一样的代码,事上儿也也没怪我们自己啊”

虎子一听急了,“为啥不怪的人了,我们自己比的人先一步找内存拿走了 i,那的人得等我们自己加完自己再用啊,不信你可以以打电话问内存那家伙,看看你想做什么样我们自己二号车间先来的”

“好好好,你先冷静一下,你看我们自己又不知道的人就去拿了,时候情有可原吗,再说现自己这件现自己出了,我们自己应该一起坐下来想个办法避免时候再次出现这种问题,如果我你想做什么样?”

虎子叹了口气问道:“如果我说说你有想做什么样样办法?”

我继续说道:“你看啊,像咱们在执行 i++ 这种操作方式的自己就不应该被干扰”

“不被干扰?”

“对,比如虎子的人二号车间在访问 i 的自己,我们自己一号车间就也没访问,还能等着,等的人访问完成我们自己再来,非常简单的办法却很有用”

虎子听完一愣,“时候而是加锁吗?我在想怪程序员做 i++ 前都没加锁?”

“确实是加锁,自己这种简单操作方式还要程序员来加锁那也太麻烦了,咱们 CPU 内部处理好就行了”

“内部处理,你也想为啥实现?”,虎子问到。

“这,,让我感觉・・・”,虎子问到了具体实现,我倒还没想到这一步。

自己,一旁的老 K 站了来讲:“我倒是是个办法,可以以找总线主任啊,他是负责协调各个车间使用系统总线访问内存的总指挥,让他在中间协调一下应该不难”

老 K 一语点醒梦中人,一会我们自己我去找了总线主任,后来我们自己商量出了一套解决方案:我们自己定义了自己叫原子操作方式的东西,表示确实自己不可切分的动作,谁要执行原子操作方式,总线主任就在系统总线上加上自己 LOCK#信号,其他车间的先去访问内存就得等着,直到原子操作方式指令执行完毕。

我们自己把这套方案上报了领导,很快就批下来了,后面我们自己 8 个车间都按照这套方案来工作,时候程序员们把 i++ 自己动作换成原子操作方式后,问题可以迎刃而解。

自己施行了一段时间自己,各个车间却开始大倒苦水:就时候某个车间要执行自己原子操作方式,就让总线主任把系统总线锁住,其他车间我们自己没有法访问内存,都干不了活了,严重影响工作效率。

抱怨归抱怨,在都没更更合适替代方案出现之前,日子还得过下去。

缓存引发的问题

自己,没过多久,数据不一致问题又一次出现了。

这一次,倒也也没加法的问题,我们自己两车间而且时候各自缓存的原因,先后修改了变量的值,对方都没即时知道,误用了错误的值,以致酿成大错。

“阿 Q,上次那办法好是好,可解决不了这一次的问题啊”,虎子再次找上门来。

“你来的正好,我正先去找如果我事上呢”

“哦,是吗,难不成如果我到破解之道了?”

“而是一些初步的想法,问题的核心在于现自己咱们各个车间各自为政,都有的人的私有缓存,各自修改数据后向内存更新时也不互相打招呼,缺少自己联络机制”

虎子点了点头,“确实,假如咱们还能建立自己联络机制,来对各个车间的缓存内容进行统一管理是吗?”

“对!事上儿咱俩说了可不上,我建议召集 8 个核心车间的代表,统一开自己会议,详细讨论下本来问题。哦,对了,把总线主任也叫上,他经验丰富说不定能提供一些思路”

缓存一致性协议 MESI

很快,咱们 CPU 的 8 个核心车间就为此问题隆重举行了会议,时候取得了非常重要的成果。

我们自己牵了一条新的专线,把 8 个核心车间连接起来,用于各个车间之间进行信息沟通,不同于 CPU 外部的总线系统,大家把本来叫片内总线。

新的线路铺设好了,时候大家就可以以通过这条线路即时沟通,为了解决之前出现的问题,大家还制定了一套规则,叫做缓存一致性协议。

规则里面规定了所有车间的缓存单元 —— 缓存行有四种状态:

已修改 Modified (M)

缓存行现自己被修改了,与内存的值不一样。确实别的 CPU 内核要读内存这块数据,要赶在这之前把该缓存行回写到主存,把状态变为共享 (S).

独占 Exclusive (E)

缓存行只在当前 CPU 核心缓存中,时候和内存中数据一样。当别的 CPU 核心读取它时,状态变为共享;确实当前 CPU 核心修改了它,就要变为已修改状态。

共享 Shared (S)

缓存行存在于多个 CPU 核心的缓存中,时候和内存中的内容一致。

无效 Invalid (I)

缓存行是无效的

四种状态之间的转换是自己:

按照这套规则,大家也没再像现自己那样随意了,各车间对自家缓存进行读写时,都要相互通一下气,避免使用过时的数据。

除此之外,还规定确实一块内存区域被多个车间都缓存,就没有允了无个车间同时去修改缓存了。

会议还有另外自己收获,现自己被各车间诟病的每次原子操作方式都要锁定总线,导致大家还能访问内存的都只能干等着的问题也鼓励了解决。时候总线主任没有还能锁定总线了,通过这次的缓存一致性协议就可以以办到。

自此时候,数据不一致的问题总事实上根治了,咱们 8 个车间又可以以愉快的工作了。