首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

伪共享概念与Java解决方案

首先,计算机工程师为了提高CPU的利用率,平衡CPU与内存之间的速度差异,在CPU里面设计了三级缓存。CPU在向内存发起IO操作的时候,一次性会读取64个字节的数据作为一个缓存行,缓存到CPU的高速缓存里面。

在Java中一个long类型是8个字节,意味着一个缓存行可以存储8个long类型的变量。这个设计是基于空间局部性原理来实现的,也就是说,如果一个存储器的位置被引用,那么将来它附近的位置也会被引用。

所以缓存行的设计对于CPU来说,可以有效地减少和内存的交互次数,从而避免了CPU的IO等待,以提升CPU的利用率。正是因为这种缓存行的设计,导致如果多个线程修改同一个缓存行里面的多个独立变量的时候,基于缓存一致性协议,就会无意中影响了彼此的性能,这就是伪共享。

比如,CPU0上运行的线程想要更新变量X,CPU1上的线程想要更新变量Y,而X/Y/Z都在同一个缓存行里面。每个线程都需要去竞争缓存行的所有权对变量做更新,基于缓存一致性协议。一旦运行的某个CPU上的线程获得了所有权并执行了修改,就会导致其他CPU中的缓存行失效。这就是伪共享问题的原理。

解决办法有两个:

使用对齐填充。因为一个缓存行大小是64个字节,如果读取的目标数据小于64个字节,可以增加一些无意义的成员变量来填充。

在Java8里面提供了@Contented注解。它也是通过缓存行填充来解决伪共享的问题。被@Contented注解声明的类或者字段,会被加载到独立的缓存行上。

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20230419A06FDD00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券