圖解Disruptor框架(一):初識Ringbuffer
圖解Disruptor框架(一):初識Ringbuffer
概述
1、 什麼是Disruptor?為什麼是Disruptor?
Disruptor是一個性能十分強悍的無鎖高併發框架。在JUC併發包中,號稱是效能最好的ArrayBlockingQueue(簡稱:ABQ),在Disruptor的面前,也只能低下驕傲的頭顱了。現在我們來看一下官方給出的測試資料。
吞吐量
上圖是官方給出的在不同的模式下,使用ABQ以及Disruptor的吞吐量對比圖。可見,在相同的模式之下,ABQ的效能跟Disruptor的效能不是一個數量級的。
接下來,看看耗時怎麼樣:
耗時對比
毫無疑問,ABQ又敗下陣來。稍微分析一下原因就可以知道為什麼會是這個樣子的,我們在ABQ的原始碼中可以看到:
- public void put(E e) throws InterruptedException {
- checkNotNull(e);
- final ReentrantLock lock = this.lock;
- // 在這裡,獲取不到鎖的執行緒只有阻塞了。
- lock.lockInterruptibly();
- try {
- while (count == items.length)
- notFull.await();
- enqueue(e);
- } finally {
- lock.unlock();
- }
- }
- public E take() throws InterruptedException {
- final ReentrantLock lock = this.lock;
- // 在這裡,獲取不到鎖的執行緒只有阻塞了。
- lock.lockInterruptibly();
- try {
- while (count == 0)
- notEmpty.await();
- return dequeue();
- } finally {
- lock.unlock();
- }
- }
ABQ內部,不論是put()還是take()都使用了鎖對資源進行同步,獲取不到鎖的執行緒就只能阻塞了。但是相比於ABQ,Disruptor號稱是不使用鎖進行資源同步的。孰優孰劣,在此Disruptor先勝一局。這裡先留個懸念,既然Disruptor不使用鎖,那麼他是怎麼做到的?
在對Disruptor進行深入的瞭解之前,我們先來看下Disruptor的核心資料結構--RingBuffer。
RingBuffer
RingBuffer就是下面這個東西:
RingBuffer
先來簡單的介紹一下Ringbuffer這個名字,這個名字有兩個特點:
- Ring:環形的。
- Buffer:快取。
這一節先介紹第一個特點,環形的。(關於快取,簡單的說,Disruptor使用了一個記憶體預載入的機制,在構造Ringbuffer的時候已經初始化好了資料。每次存資料,其實是對資料的更新。)
RingBuffer本質上是一個數組,因此對資料的索引十分的方便。
獲取第四個元素
隨著資料的增多,序號的增大,這個環可能會變成以下的這個樣子:
取第12個位置的元素
想取第十二個位置的元素也非常的簡單,初中數學告訴我們,只需要在:
12 % 10 = 2 這個位置,就可以取到這個元素。
以上就是Disruptor最核心的資料結構了。這個框架中的其他一切元件:生產者、消費者、序號生成器等等之類的元件,都是為了服務這個RingBuffer而誕生的。
總結
今天這篇就是簡單的介紹一下disruptor這個框架。大家只需要先有個印象,知道有這麼一個東西就行了。後續我會慢慢的將這些東西補充完全。