这里先不提那些编译器方面的优化,仅仅看一下基于无锁环形队列的生产者消费者模型的工作流程。上一个图先:
其中,buffer是一个数组,用来模拟环形队列。slowest_reader记录最慢的reader读取数据的位置,主要用来防止写者写得太快而覆盖掉还未被读的数据。max_read_cursor是目前能够读取的最远的数据的位置,这个位置应该是>=所有读者的位置的(初始化时为0,小于所有读者的位置,所以初始化时读者是不能读取数据的)。write_cursor是当前最快的写者的写入的位置。那么如果再来一个写者请求写入怎么办?很好办,把write_cursor++,然后写入到这个位置即可。所以,disruptor是支持多个写者同时写入数据的(只是发布时要有严格的先后顺序)。reader_cursor数组用来记录每个读者的位置。
那么,现在写者要写入数据,该怎么做呢?前面已经说过了,write_cursor++,然后写入到这个位置。如下图:
上图中,max_read_cursor也更新了,这个更新其实是在写者发布他的写入后才有的。
现在,ring buffer中有数据了,读者可以读取数据了(标志是读者的cursor<=max_read_cursor)。读的时候就是把max_read_cursor作为最大的可读位置。而这个最大可读位置可能比当前的某个读者的读取位置大了不止一个位置。因为有可能写者写得比较快,完全可以写入很多个位置而读者还在后面,那么这种情况下读者就可以一下子取出很多数据,而不是一个一个地去读取。这也是disruptor的一个特点。
这里只是讲了disruptor的基本流程,一些同步的细节并没有说。读者在buffer中没有数据可读时该如何等待这是一个和业务场景强相关的逻辑,可以轮询,也可以睡眠,这个后面再说。
原文地址:http://blog.csdn.net/joseph_1118/article/details/25343553