当前位置: 首页 > article >正文

简述一下伪共享的概念以及如何避免

缓存行

计算机工程师为了提高 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 注解声明的类或者字段,会被加载到独立的缓存行上。

http://www.kler.cn/a/106597.html

相关文章:

  • 深入理解 source 和 sh、bash 的区别
  • 时钟之CSS+JS版
  • JDBC-Mysql 时区问题详解
  • 基于汇编语言的贪吃蛇程序
  • Springboot定时任务
  • STM32芯片EXIT外部中断的配置与原理
  • 记录:获取windows当前登录的用户信息
  • R语言的物种气候生态位动态量化与分布特征模拟实践技术
  • P1868 饥饿的奶牛
  • 2023深耕kotlin,谈谈前景
  • webgl速记之如何根据用户硬件进行性能模式OR质量模式的切换的设计思路
  • Jetpack:019-Jetpack的导航二(传递数据)
  • 基于大数据的时间序列股价预测分析与可视化 - lstm 计算机竞赛
  • 如何做好建筑翻译呢
  • C++——C++入门(二)
  • 读书笔记:c++对话系列,模板方法模式(Template Method Pattern)
  • #力扣:2315. 统计星号@FDDLC
  • 电大搜题:开启智慧学习新时代
  • 2023年第四届MathorCup大数据竞赛(A题)|坑洼道路检测和识别|数学建模完整代码+建模过程全解全析
  • 软件工程——期末复习知识点汇总
  • python+request接口自动化框架
  • Transformer模型 | 用于目标检测的视觉Transformers训练策略
  • 多测师肖sir_高级金牌讲师__接口测试之tonken (5.6)
  • 异步编程详解(.NET)
  • java毕业设计基于springboot的民宿预订信息网站
  • Matter.js 插件:matter-wrap(世界是圆的)