这里先不提那些编译器方面的优化。只看一下基于无锁环形队列的生产者消费者模型的工作流程。上一个图先:
当中,buffer是一个数组,用来模拟环形队列。
slowest_reader记录最慢的reader读取数据的位置,主要用来防止写者写得太快而覆盖掉还未被读的数据。max_read_cursor是眼下可以读取的最远的数据的位置。这个位置应该是>=全部读者的位置的(初始化时为0,小于全部读者的位置,所以初始化时读者是不能读取数据的)。write_cursor是当前最快的写者的写入的位置。
那么假设再来一个写者请求写入怎么办?非常好办,把write_cursor++,然后写入到这个位置就可以。所以,disruptor是支持多个写者同一时候写入数据的(仅仅是公布时要有严格的先后顺序)。reader_cursor数组用来记录每一个读者的位置。
那么,如今写者要写入数据,该怎么做呢?前面已经说过了,write_cursor++,然后写入到这个位置。
例如以下图:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvSm9zZXBoXzExMTg=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="">
上图中,max_read_cursor也更新了,这个更新事实上是在写者公布他的写入后才有的。
如今。ring buffer中有数据了,读者能够读取数据了(标志是读者的cursor<=max_read_cursor)。读的时候就是把max_read_cursor作为最大的可读位置。
而这个最大可读位置可能比当前的某个读者的读取位置大了不止一个位置。
由于有可能写者写得比較快,全然能够写入非常多个位置而读者还在后面,那么这样的情况下读者就能够一下子取出非常多数据,而不是一个一个地去读取。
这也是disruptor的一个特点。
这里仅仅是讲了disruptor的基本流程。一些同步的细节并没有说。
读者在buffer中没有数据可读时该怎样等待这是一个和业务场景强相关的逻辑。能够轮询,也能够睡眠,这个后面再说。