【Java】一文全面了解伪共享(false sharing)问题

通过本文,可以收获如下知识:
① MESI协议相关
② 图例讲解伪共享问题
③ 实例讲解伪共享问题带来的性能问题
④ 使用perf进行性能分析
⑤ @Contended注解的原理

一、概述

在本文中,我们会看到伪共享问题有时会使多线程程序适得其反。

首先,我们将从缓存和局部性理论开始。然后我们会自己重写一个LongAdder并发工具类,并将其与java.util.concurrent中的实现进行基准测试。在本文中,我们将使用基准测试的结果来调研伪共享对程序性能的影响。

本文中与java相关的部分很大程度上依赖于对象的内存布局。由于这些布局细节不是JVM规范的一部分,由实现者自行决定,因此我们将只关注一个特定的JVM实现:HotSpot JVM。在本文中,JVM和HotSpot JVM术语也可以互换使用。

二、缓存行(Cache Line) 和 一致性(Coherency)

处理器会使用不同级别的缓存——当处理器从主存读取一个值时,它可能缓存该值以提高性能。

事实证明,大多数现代处理器不仅缓存了请求的值,还缓存了一些这个请求的值的附近的值。这种优化基于空间局部性的思想,可以显著提高应用程序的整体性能。简单地说,处理器缓存是根据cache line工作的,而不是单个可缓存值。

当多个处理器在相同或附近的内存位置上运行时,它们可能最终共享相同的缓存线。在这种情况下,保持不同核心中的重叠缓存彼此一致是很重要的。保持这种一致性的行为称为缓存一致性。

有相当多的协议来维护CPU核之间的缓存一致性。在本文中,我们将讨论MESI协议。

2.1 MESI协议

在MESI协议中,每条cache line可以处于以下四种不同的状态之一:Modified, Exclusive, Shared, Invalid。MESI是这些状态的首字母缩写。

为了更好地理解这个协议是如何工作的,让我们来看一个示例。假设两个核要从附近的内存位置读取数据:

你可能感兴趣的:(【Java】一文全面了解伪共享(false sharing)问题)