1. 程式人生 > >圖解Disruptor框架(一):初識Ringbuffer

圖解Disruptor框架(一):初識Ringbuffer

圖解Disruptor框架(一):初識Ringbuffer

概述

1、 什麼是Disruptor?為什麼是Disruptor?
Disruptor是一個性能十分強悍的無鎖高併發框架。在JUC併發包中,號稱是效能最好的ArrayBlockingQueue(簡稱:ABQ),在Disruptor的面前,也只能低下驕傲的頭顱了。現在我們來看一下官方給出的測試資料。

吞吐量
吞吐量

上圖是官方給出的在不同的模式下,使用ABQ以及Disruptor的吞吐量對比圖。可見,在相同的模式之下,ABQ的效能跟Disruptor的效能不是一個數量級的。

接下來,看看耗時怎麼樣:

耗時對比
耗時對比

毫無疑問,ABQ又敗下陣來。稍微分析一下原因就可以知道為什麼會是這個樣子的,我們在ABQ的原始碼中可以看到:

  1. public void put(E e) throws InterruptedException
  2. checkNotNull(e); 
  3. final ReentrantLock lock = this.lock; 
  4. // 在這裡,獲取不到鎖的執行緒只有阻塞了。 
  5. lock.lockInterruptibly(); 
  6. try
  7. while (count == items.length) 
  8. notFull.await(); 
  9. enqueue(e); 
  10. } finally
  11. lock.unlock(); 
  12.  
  13. public E take() throws InterruptedException
  14. final ReentrantLock lock = this.lock; 
  15. // 在這裡,獲取不到鎖的執行緒只有阻塞了。 
  16. lock.lockInterruptibly(); 
  17. try
  18. while (count == 0
  19. notEmpty.await(); 
  20. return dequeue(); 
  21. } finally
  22. lock.unlock(); 

ABQ內部,不論是put()還是take()都使用了鎖對資源進行同步,獲取不到鎖的執行緒就只能阻塞了。但是相比於ABQ,Disruptor號稱是不使用鎖進行資源同步的。孰優孰劣,在此Disruptor先勝一局。這裡先留個懸念,既然Disruptor不使用鎖,那麼他是怎麼做到的?

在對Disruptor進行深入的瞭解之前,我們先來看下Disruptor的核心資料結構--RingBuffer

RingBuffer

RingBuffer就是下面這個東西:

RingBuffer
RingBuffer

先來簡單的介紹一下Ringbuffer這個名字,這個名字有兩個特點:

  • Ring:環形的。
  • Buffer:快取。

這一節先介紹第一個特點,環形的。(關於快取,簡單的說,Disruptor使用了一個記憶體預載入的機制,在構造Ringbuffer的時候已經初始化好了資料。每次存資料,其實是對資料的更新。)

RingBuffer本質上是一個數組,因此對資料的索引十分的方便。

獲取第四個元素
獲取第四個元素

隨著資料的增多,序號的增大,這個環可能會變成以下的這個樣子:

取第12個位置的元素
取第12個位置的元素

想取第十二個位置的元素也非常的簡單,初中數學告訴我們,只需要在:

12 % 10 = 2 這個位置,就可以取到這個元素。

以上就是Disruptor最核心的資料結構了。這個框架中的其他一切元件:生產者、消費者、序號生成器等等之類的元件,都是為了服務這個RingBuffer而誕生的。

總結

今天這篇就是簡單的介紹一下disruptor這個框架。大家只需要先有個印象,知道有這麼一個東西就行了。後續我會慢慢的將這些東西補充完全。

參考資料

  1. 官方的設計說明以及測試 http://101.96.10.64/lmax-exchange.github.io/disruptor/files/Disruptor-1.0.pdf
  2. Ringbuffer設計的簡要介紹 http://mechanitis.blogspot.com/2011/06/dissecting-disruptor-whats-so-special.html