將系統(tǒng)性能優(yōu)化到極致,永遠是程序愛好者所努力的一個方向。在java并發(fā)領(lǐng)域,也有很多的實踐與創(chuàng)新,小到樂觀鎖、CAS,大到netty線程模型、纖程Quasar、kilim等。Disruptor是一個輕量的高性能并發(fā)框架,以驚人的吞吐量而受到廣泛的關(guān)注。Disruptor為提高程序的并發(fā)性能,提供了很多新的思路,比如:
緩存行填充,消除偽共享;
RingBuffer無鎖隊列設(shè)計;
預分配緩存對象,使用緩存的循環(huán)覆蓋取代緩存的新增刪除等;
下文將從源碼角度解析Disruptor的實現(xiàn)原理。
1 Disruptor術(shù)語
Disruptor有很多自身的概念,使得初學者看代碼會比較費勁。因此在深入Disruptor原理之前,需要先了解一下Disruptor主要的幾個核心類或接口。
Sequence: 采用緩存行填充的方式對long類型的一層包裝,用以代表事件的序號。通過unsafe的cas方法從而避免了鎖的開銷;
Sequencer: 生產(chǎn)者與緩存RingBuffer之間的橋梁。單生產(chǎn)者與多生產(chǎn)者分別對應(yīng)于兩個實現(xiàn)SingleProducerSequencer與MultiProducerSequencer。Sequencer用于向RingBuffer申請空間,使用publish方法通過waitStrategy通知所有在等待可消費事件的SequenceBarrier;
WaitStrategy: WaitStrategy有多種實現(xiàn),用以表示當無可消費事件時,消費者的等待策略;
SequenceBarrier: 消費者與緩存RingBuffer之間的橋梁。消費者并不直接訪問RingBuffer,從而能減少RingBuffer上的并發(fā)沖突;
EventProcessor: 事件處理器,是消費者線程池Executor的調(diào)度單元,是對事件處理EventHandler與異常處理ExceptionHandler等的一層封裝;
Event: 消費事件。Event的具體實現(xiàn)由用戶定義;
RingBuffer: 基于數(shù)組的緩存實現(xiàn),也是創(chuàng)建sequencer與定義WaitStrategy的入口;
Disruptor: Disruptor的使用入口。持有RingBuffer、消費者線程池Executor、消費者集合ConsumerRepository等引用。
2 Disruptor源碼分析
2.1 Disruptor并發(fā)模型
并發(fā)領(lǐng)域的一個典型場景是生產(chǎn)者消費者模型,常規(guī)方式是使用queue作為生產(chǎn)者線程與消費者線程之間共享數(shù)據(jù)的方法,對于queue的讀寫避免不了讀寫鎖的競爭。Disruptor使用環(huán)形緩沖區(qū)RingBuffer作為共享數(shù)據(jù)的媒介。生產(chǎn)者通過Sequencer控制RingBuffer,以及喚醒等待事件的消費者,消費者通過SequenceBarrier監(jiān)聽RingBuffer的可消費事件。考慮一個場景,一個生產(chǎn)者A與三個消費者B、C、D,同時D的事件處理需要B與C先完成。則該模型結(jié)構(gòu)如下:
在這個結(jié)構(gòu)下,每個消費者擁有各自獨立的事件序號Sequence,消費者之間不存在共享競態(tài)。SequenceBarrier1監(jiān)聽RingBuffer的序號cursor,消費者B與C通過SequenceBarrier1等待可消費事件。SequenceBarrier2除了監(jiān)聽cursor,同時也監(jiān)聽B與C的序號Sequence,從而將最小的序號返回給消費者D,由此實現(xiàn)了D依賴B與C的邏輯。
RingBuffer是Disruptor高性能的一個亮點。RingBuffer就是一個大數(shù)組,事件以循環(huán)覆蓋的方式寫入。與常規(guī)RingBuffer擁有2個首尾指針的方式不同,D