1
0
mirror of https://github.com/Snailclimb/JavaGuide synced 2025-06-16 18:10:13 +08:00

Merge pull request #2262 from 2382546457/main

Update disruptor-questions.md
This commit is contained in:
Guide 2024-02-18 16:34:52 +08:00 committed by GitHub
commit c5260fae12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

View File

@ -115,7 +115,7 @@ Disruptor 真的很快,关于它为什么这么快这个问题,会在后文
## Disruptor 为什么这么快?
- **RingBuffer环形数组** : Disruptor 内部的 RingBuffer 是通过数组实现的。由于这个数组中的所有元素在初始化时一次性全部创建,因此这些元素的内存地址一般来说是连续的。这样做的好处是,当生产者不断往 RingBuffer 中插入新的事件对象时,这些事件对象的内存地址就能够保持连续,从而利用 CPU 缓存的局部性原理,将相邻的事件对象一起加载到缓存中,提高程序的性能。这类似于 MySQL 的预读机制将连续的几个页预读到内存里。除此之外RingBuffer 基于数组还支持批量操作一次处理多个元素、还可以避免频繁的内存分配和垃圾回收RingBuffer 是一个固定大小的数组,当向数组中添加新元素时,如果数组已满,则新元素将覆盖掉最旧的元素)。
- **避免了伪共享问题**CPU 缓存内部是按照 Cache Line缓存行管理的一般的 Cache Line 大小在 64 字节左右。Disruptor 为了确保目标字段独占一个 Cache Line会在目标字段前后增加了 64 个字节的填充(前 56 个字节和后 8 个字节),这样可以避免 Cache Line 的伪共享False Sharing问题。
- **避免了伪共享问题**CPU 缓存内部是按照 Cache Line缓存行管理的一般的 Cache Line 大小在 64 字节左右。Disruptor 为了确保目标字段独占一个 Cache Line会在目标字段前后增加字节填充(前 56 个字节和后 56 个字节),这样可以避免 Cache Line 的伪共享False Sharing问题。同时,为了让 RingBuffer 存放数据的数组独占缓存行,数组的设计为 无效填充128字节+ 有效数据。
- **无锁设计**Disruptor 采用无锁设计避免了传统锁机制带来的竞争和延迟。Disruptor 的无锁实现起来比较复杂,主要是基于 CAS、内存屏障Memory Barrier、RingBuffer 等技术实现的。
综上所述Disruptor 之所以能够如此快,是基于一系列优化策略的综合作用,既充分利用了现代 CPU 缓存结构的特点,又避免了常见的并发问题和性能瓶颈。