写点什么

Disruptor 高性能堆内队列 系列二

作者:Nick
  • 2022 年 6 月 07 日
  • 本文字数:1211 字

    阅读完需:约 4 分钟

Disruptor 高性能堆内队列 系列二

本文使用「署名 4.0 国际 (CC BY 4.0)」许可协议,欢迎转载、或重新修改使用,但需要注明来源。 署名 4.0 国际 (CC BY 4.0)


本文作者: Nicksxs


创建时间: 2022-02-27


本文链接: Disruptor 高性能堆内队列 系列二


这里开始慢慢深入的讲一下 disruptor,首先是 lock free , 相比于前面介绍的两个阻塞队列,


disruptor 本身是不直接使用锁的,因为本身的设计是单个线程去生产,通过 cas 来维护头指针,


不直接维护尾指针,这样就减少了锁的使用,提升了性能;第二个是这次介绍的重点,


减少 false sharing 的情况,也就是常说的 伪共享 问题,那么什么叫 伪共享 呢,


这里要扯到一些 cpu 缓存的知识,



譬如我在用的这个笔记本



这里就可能看到 L2 Cache 就是针对每个核的



这里可以看到现代 CPU 的结构里,分为三级缓存,越靠近 cpu 的速度越快,存储容量越小,


而 L1 跟 L2 是 CPU 核专属的每个核都有自己的 L1 和 L2 的,其中 L1 还分为数据和指令,


像我上面的图中显示的 L1 Cache 只有 64KB 大小,其中数据 32KB,指令 32KB,


而 L2 则有 256KB,L3 有 4MB,其中的 Line Size 是我们这里比较重要的一个值,


CPU 其实会就近地从 Cache 中读取数据,碰到 Cache Miss 就再往下一级 Cache 读取,


每次读取是按照缓存行 Cache Line 读取,并且也遵循了“就近原则”,也就是相近的数据有可能也会马上被读取,所以以行的形式读取,然而这也造成了 false sharing


因为类似于 ArrayBlockingQueue,需要有 takeIndex , putIndex , count , 因为在同一个类中,


很有可能存在于同一个 Cache Line 中,但是这几个值会被不同的线程修改,


导致从 Cache 取出来以后立马就会被失效,所谓的就近原则也就没用了,因为需要反复地标记 dirty 脏位,然后把 Cache 刷掉,就造成了false sharing这种情况而在 disruptor 中则使用了填充的方式,让我的头指针能够不产生false sharing


class LhsPadding{    protected long p1, p2, p3, p4, p5, p6, p7;}
class Value extends LhsPadding{ protected volatile long value;}
class RhsPadding extends Value{ protected long p9, p10, p11, p12, p13, p14, p15;}
/** * <p>Concurrent sequence class used for tracking the progress of * the ring buffer and event processors. Support a number * of concurrent operations including CAS and order writes. * * <p>Also attempts to be more efficient with regards to false * sharing by adding padding around the volatile field. */public class Sequence extends RhsPadding{
复制代码


通过代码可以看到,sequence 中其实真正有意义的是 value 字段,因为需要在多线程环境下可见也


使用了volatile 关键字,而 LhsPaddingRhsPadding 分别在 value 前后填充了各


7 个 long 型的变量,long 型的变量在 Java 中是占用 8 bytes,这样就相当于不管怎么样,


value 都会单独使用一个缓存行,使得其不会产生 false sharing 的问题。

发布于: 刚刚阅读数: 4
用户头像

Nick

关注

还未添加个人签名 2017.12.22 加入

写代码的阿森 https://nicksxs.me https://nicksxs.com 也可以看我的博客

评论

发布
暂无评论
Disruptor 高性能堆内队列 系列二_Java_Nick_InfoQ写作社区