真实字节二面:什么是伪共享?

前端 2023-07-05 17:29:38
36阅读

这个问题来源于近期一个盆友字节数招聘面试遇到的,最终他也取得成功取得了字节数offer,这个问题我觉得很有可能挺多的人不太清晰,因此想拿出来独立说一说。

好啦,使我们进到主题。

什么叫伪共享资源

最先大家都了解,伴随着CPU和运行内存的发展趋势速率差别的难题,造成 CPU的速率远远地快于运行内存,因此一般如今的CPU都添加了高速缓存,便是常说的处理不一样硬件配置中间的特性差别难题。

那样的话,非常简单的大道理,添加了缓存文件,就必定会造成 缓存文件一致性的难题,从而,又引进了缓存文件一致性协议书。(假如你永远不知道,提议去百度一下,这儿不做进行)

CPU缓存,说白了,越接近CPU的缓存文件速率越快,容积越小,工程造价成本费也越高,而高速缓存一般能够 分成L1、L2、L3三级缓存,依照特性的区划:L1>L2>L3。

照片

而实际上,数据信息在缓存文件內部全是依照行来储存的,这就称为缓存文件行。缓存文件行一般全是2的整数金额幂个字节数,一般来说范畴在32-256个字节数中间,如今更为普遍的缓存文件行的尺寸在64个字节数。

因此,依照这一储存方法,缓存文件中的数据信息并并不是一个个独立的自变量的储存方法,只是好几个自变量会放进一行中。

大家常说的一个事例便是二维数组和链表,二维数组的内存地址是持续的,在我们去载入二维数组中的原素时,CPU会把二维数组中事后的数个原素也载入到缓存文件中,为此提高工作效率,可是链表则不容易,换句话说,内存地址持续的自变量才有可能被放进一个缓存文件行中。

在好几个进程高并发改动一个缓存文件行中的好几个自变量时,因为只有另外有一个进程去实际操作缓存文件行,可能造成 特性的降低,这个问题就称作伪共享资源。

为何只有一个进程能去实际操作?大家举个具体的板栗来表明这类状况:

假定缓存文件中有x,y2个自变量,她们另外早已在不一样的三级缓存当中。

这时候有两个进程A和B另外去改动坐落于Core1和Core2的自变量x和y。

假如进程A去改动Core1的缓存文件中的x自变量,因为缓存文件一致性协议书,Core2中相匹配的缓存文件了x自变量的缓存文件已然会无效,他会被强制性从主运行内存中再次去载入自变量。

那样的话,经常的浏览主运行内存,缓存文件基础都无效了,可能造成 特性的降低,这就是伪共享资源的难题。

照片

怎样防止?

即然早已知道什么叫伪共享资源,那麼如何防止这类状况的产生?

更改行储存的方法?想都别想了。

剩余行得通的方式 便是添充,假如这一行只有我自己这一个数据信息那不就可以了嘛?

的确就这样,处理方法一般有下列二种。

字节数添充

在JDK8以前,能够 根据添充字节数的方法来防止伪共享资源的难题,以下编码所显示:

照片

自定添充

一般而言,缓存文件行有64字节数,我们知道一个long是八个字节数,添充五个long以后,一共便是48个字节数。

而 Java 中目标头在32位系统下占有八个字节数,64位系统下占有16个字节数,那样添充五个long型就可以铺满64字节数,也就是一个缓存文件行。

@Contented注释

JDK8及其以后的版本号 Java 出示了sun.misc.Contended 注释,根据@Contented注释就可以处理伪共享资源的难题。

照片

注释方法

应用@Contented注释后会提升128字节数的padding,而且必须打开-XX:-RestrictContended选择项后才可以起效。

因此,根据之上二种方法你能发觉,目标头尺寸和缓存文件行的尺寸都和电脑操作系统十位数相关,JDK的注释帮你解决了这个问题,因此强烈推荐尽可能应用注释的方法来完成。

尽管解决了伪共享资源难题,可是这类添充的方法也消耗了缓存文件資源,本来仅有8B的尺寸,就是应用了64B缓存文件室内空间,导致了缓存文件資源的消耗。

并且我们知道,缓存文件又小又贵,时间和空间的选择要自身酌情处理。

具体运用

在Java中出示了好几个分子自变量的实际操作类,便是例如AtomicLong、AtomicInteger这种,根据CAS的方法去升级自变量,可是不成功会无尽磁矩试着,造成 CPU資源的消耗。

为了更好地处理分布式系统下的这一缺陷,JDK8中增加了LongAdder类,他的应用便是对处理伪共享资源的具体运用。

LongAdder承继自Striped64,內部维护保养了一个Cell二维数组,核心内容便是把单独自变量的市场竞争分拆,线程同步下假如一个Cell市场竞争不成功,继而去别的Cell再度CAS再试。

照片

Striped64成员函数

处理伪共享资源的真实的关键就在Cell二维数组,能够 见到,Cell二维数组应用了Contented注释。

在上面大家提及二维数组的内存地址全是持续的,因此二维数组内的原素常常会被放进一个缓存文件行,那样的话便会产生伪共享资源的难题,危害特性。

这儿应用Contented开展添充,就防止了伪共享资源的难题,促使二维数组中的原素不会再共享资源一个缓存文件行。

照片

处理伪共享资源

好啦,今日的內容就到这儿,我是艾小仙子,我的slogan还没有想好,可是大家下次见。

the end
免责声明:本文不代表本站的观点和立场,如有侵权请联系本站删除!本站仅提供信息存储空间服务。