Disruptor-03 Ringbuffer的高性能设计

2020-09-10  本文已影响0人  rock_fish

Ringbuffer数据结构

image.png

初步解读:

  1. 数组是连续的内存空间,连续内存空间的读写效率较高
  2. 仅申请一次空间,逻辑上构成环形结构,复用内存空间.大大减少了内存空间的申请和释放动作.
  3. FIFO,读取数据时,可以实现非常好的批处理.

生产者线程 和 消费者线程之间通信的桥梁(共享变量)

作为临界区资源,必然会有共享变量,为了保证线程安全所需要解决的问题:

通常的操作是:

  1. 原子性修改.(循环+CAS) ,性能高
  2. 修改动作串行化, 性能低

知道怎么操作后,还需要进一步思考以下几个问题:

线程安全问题的关键也在于"变",对于这个队列来说变得部分需要我们必须关注的是:

  1. 生产者:消息待放置的位置
  2. 消费者:可消费的消息的位置.

特别要留意: ringbuffer数组大小是固定的,没有变化.

ringbuffer中的循环+cas操作

对上边变的部分,从源码中看可以知道,是通过循环+cas操作来保证数据的安全性的

变更可见性以及隔离控制(缓存行填充 难度中)

生产者往某个元素中放置了数据后,消费者要能知道(可见),
消费者消费完了某个位置的元素后,生产者要能知道(可见),

以面向对象的思想来考虑,我们将这些信息作为属性放置到RingBuffer这个对象中,生产者,消费者在不同线程中,通过RingBuffer这个对象的相关属性获取这些位置信息

那么这个RingBuffer对象的内存,在线程间共享,其属性变量(内存中的数据)的修改要保证线程间可见.

这个线程间到底是什么样的线程之间??? 运行在不同cpu核的线程之间?不仅仅是这样,这里的关键是要梳理一下计算机组成原理以及操作系统的一些知识.

思考一个问题:Netty里设置线程池中线程数目的时候,通常设置为多少,有么有一个参考基数? 答案里有一个CPU核数.那么CPU核与线程之间什么关系呢?

CPU的线程数概念仅仅只针对Intel的CPU才有用,因为它是通过Intel超线程技术来实现的,最早应用在Pentium4上。如果没有超线程技术,一个CPU核心对应一个线程。所以,对于AMD的CPU来说,只有核心数的概念,没有线程数的概念。

在没有超线程这种情况下,CPU的核数也就是并行运行的线程数.

CPU怎么操作内存中的数据?

为了弥补CPU和内存两者之间的速度差异,充分使用把CPU的高性能,而不是让它在那儿空转等待,现代CPU架构中引入了高速缓存,分为L1 cache,L2 cache和L3 cache

image.png

内存中的指令、数据,会被加载到高速缓存,在95%的情况下,CPU都只需要访问L1-L3 Cache,而不是直接 由CPU访问内存去拿。

image.png

MESI

缓存一致性问题,操作系统通过MESI这么个协议,达到一个最终一致性,可是对应用程序来说在时效性上没有保证.

内存屏障

为了在时效性上有保证,我们在程序中明确的要求时效性,通过给屏障指令.

感谢你们


001-CPU多级缓存架构

http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html

上一篇下一篇

猜你喜欢

热点阅读