最近看书看到的伪分享问题,直接触及了知识盲区。我以前从未听说过这件事。打开百度就像吃饭一样自然。
虽然在上的次数不多,但我觉得还是很重要的一个问题,而且也不难,五分钟就能搞定~
老规矩,背诵版本在文末。公众号【飞小牛肉】定期更新大厂面试题,提供背诵版和详解版
L3缓存架构
众所周知,为了缓解内存和CPU速度不匹配的矛盾,引入了缓存。它的容量比内存小得多,但交换速度却比内存快得多。
之前我们画了一个这样的分层存储架构:
其实缓存还是有细分的,也就是所谓的三级缓存结构:一级(L1)缓存,二级(L2)缓存,三级(L 3) 缓存)
越靠近 CPU 的缓存,容量越快越小。所以L1缓存容量最小但速度最快;L3缓存容量最大,速度最慢
CPU执行操作时,会先去L1缓存寻找需要的数据,如果没有找到,就会去L2缓存,再去L3缓存,如果最后三级缓存都没有命中,然后CPU会去内存被访问。
显然,CPU 走得越远,计算所需的时间就越长。所以尽量保证数据存储在L1缓存中,以提高计算量较大的情况下的运行速度。
需要注意的是CPU与L3缓存和内存的对应使用关系:
如下所示:
另外,三级缓存空间中的数据是如何组织的?也就是说,这个三级缓存中数据的存储形式是什么?
缓存线!
缓存中的基本存储单元是Cache Line。
每个 Cache Line 通常是 64 字节,即一个 Java long 类型变量是 8 个字节,一个 Cache Line 可以存储 8 个 long 类型变量。
所以你们能看出来吗~缓存中的数据不是作为单个变量存储和组织的,而是多个变量会放在一行中。
虚假分享问题 False
说了这么多,看来伪分享的问题还没有触及到。别着急,我们离真相很近了~
在程序运行过程中,由于缓存的基本单位是64字节,每次更新缓存时,缓存都会从内存中连续加载64字节。
如果访问一个long类型的数组,当数组中的一个值比如v1被加载到缓存中时,接下来的7个地址相邻的元素也会被加载到缓存中。(这也解释了为什么我们的数组总是那么快,而像链表这样的离散存储数据结构却不能享受这个好处)。
但是,这波红利很可能带来灾难。
比如我们定义了两个long类型的变量a和b,它们在内存中的地址是相邻的,会发生什么?
如果我们要访问a,那么b也将存储在缓存中。
我很困惑,这有什么问题吗?它似乎没有任何问题,这是一个多么好的功能。
来吧,我们举个例子
回想上面提到的CPU与L3缓存和内存的对应使用关系,想象一下这种情况,如果一个CPU核心线程T1在修改a,而另一个CPU核心线程T2在读取b。挑选。
当T1修改a时,除了将a加载到Cache Line之外,还会享受一波加成,还将b加载到T1所在CPU核心的Cache Line,对吧。
根据MESI缓存一致性协议,修改a后,Cache Line的状态为M(修改),而其他所有包含a的Cache Line中的a都不是最新值,所以会变成I状态( ,无效状态)
这样,T2在读取b的时候,嘿嘿,他发现自己所在的CPU核心对应的Cache Line已经过期了,mmp,从内存中重新加载需要很长时间。
问题已经很明显了,b和a没有关系,但是每次因为a的更新需要从内存中重新读取,速度就变慢了。这是虚假分享
表面上 a 和 b 是由独立的线程操作的,这两个操作之间没有任何关系。只是他们共享一个缓存行,但所有的争用冲突都源于共享。
使用更书面的解释来定义假共享:当多个线程修改相互独立的变量时,如果这些变量共享同一个缓存行,就会在不经意间影响彼此的性能,导致无法充分利用缓存线特征,这是虚假分享。
伪共享解决方案
我们举个例子来看看伪共享代码的耗时。如下图,我们定义一个Test类,其中包含两个long变量,并使用两个线程自动将这两个变量递增1亿次。,这段代码需要时间
对于伪共享,一般有两种方法,其实思路是一样的:
1):就是增加数组元素之间的间隔,让不同线程访问的元素位于不同的缓存行,空间换时间
如上所述,一个 64 字节的 Cache Line 可以存储 8 个 long 类型的变量。我们在 a 和 b 两个长型变量之间添加了 7 个长型变量,使 a 和 b 处于不同的位置。上面的缓存线:
class Pointer {
volatile long a;
long v1, v2, v3, v4, v5, v6, v7;
volatile long b;
}
再次运行程序,你会发现输出时间神奇地缩短到了955ms
2)JDK1.8 提供了@注解:就是将我们手动操作封装到这个注解中。此注释可以放在类上或字段上。我不会在这里解释它。跨度
class Test {
@Contended
volatile long a; // 填充 a
volatile long b;
}
需要注意的是默认使用这个注解是无效的,需要在JVM启动参数中加上XX:-才能生效
最后,把这个问题的记忆版本:
分类:
操作系统的东西
技术要点:
相关文章:
暂无评论内容