Halo
发布于 2022-05-23 / 103 阅读 / 0 评论 / 0 点赞

jvm 伪共享

cpu 缓存

  1. 当 CPU 执行运算的时候,它先去 L1 查找所需的数据,再去 L2,然后是 L3,最后如果这些缓存中都没有,所需的数据就要去主内存拿。走得越远,运算耗费的时间就越长。所以如果你在做一些很频繁的事,你要确保数据在 L1 缓存中
  2. CPU缓存是以缓存行(Cache line)为最小数据单位,主流大小是64个字节。
  3. 为了保证缓存数据一致性,根据MESI协议,如果一个缓存行的一个变量发生变化了, 会使其他core相同缓存行数据过期. 如果多个线程同时去写入缓存行中不同的变量,虽然明面上不同线程读写不同的数据,但是由于数据在同一缓存行上,造成缓存频繁失效,就会无意中影响彼此的性能,这就是伪共享

JVM 伪共享(false sharing)

CPU缓存是以缓存行(Cache line)为最小数据单位,缓存行是2的整数幂个连续字节,主流大小是64个字节。
如果多个变量同属于一个缓存行,在并发环境下同时修改,因为写屏障及内存一致性协议会导致同一时间只能一个线程操作该缓存行,进而因为竞争导致性能下降,这就是“伪共享”。“伪共享”是高并发场景下一个底层细节问题。

解决办法

  1. 字节对齐. 把变量大小按照缓存行的大小进行对齐。比如某个变量需要占用32个字节,然后在额外定义多个字段(比如4个long类型变量字段)来补齐整个缓存行. 这样每个变量占有一个缓存行, 就不存在缓存行被多个线程同时读写上锁情况

  2. @Contended 注解
    并且将JVM启动参数设置为XX:-RestrictContended.
    该注解可以用在字段和类上,自动帮我们进行字节补齐.


评论