Disruptor 源码分析(5) 一个生产者和多个生产者的区别

disruptor一个生产者和多个生产者的区别

一个生产者的时候用的是SingleProducerSequencer,多个的时候用的是MultiProducerSequencer.

上一篇文章说到了他们在isAvailable方法上的不同,
SingleProducerSequencer直接用cursor去判断,应为只有一个生产者的cursor,所以是没问题的.

public boolean isAvailable(long sequence)
    {
        return sequence <= cursor.get();
    }


但是MultiProducerSequencer时候,每一个生产者都有cursor,disruptor采取的做法是用一个数组来存.
而且这个数组的大小和RingBuffer的大小是一样的.因为数组的一个位置只会由一个生产者获取,而且一个位置只能被某一圈的时候获取.
(获取一个位置两次,表示一个生产者从后面追上另外一个生产者,这个是不允许的.)


这里说说他们next方法的不同:
SingleProducerSequencer,完全不同sequence来表示位置,而是用了Padding类,缓存同样也用的是Padding类

  private static class Padding
    {
        public long nextValue = Sequence.INITIAL_VALUE, cachedValue = Sequence.INITIAL_VALUE, p2, p3, p4, p5, p6, p7;
    }


可以看到Padding的p2到p7是没用的,只是为了凑够64字节.因为cpu的缓存是64字节.这样做是为了避免缓存失效.Sequence类也做了同样的事情
可以看到Padding不是线程安全的,但是对于SingleProducerSequencer来说,只有一个生产者,足够了.


MultiProducerSequencer的next方法用cursor(Sequence类)来表示位置信息.用gatingSequenceCache(Sequence类)来缓存位置信息,这是为什么呢.
来看看Sequence类吧

public long get()
    {
        return UNSAFE.getLongVolatile(paddedValue, VALUE_OFFSET);
    }

 public void set(final long value)
    {
        UNSAFE.putOrderedLong(paddedValue, VALUE_OFFSET, value);
    }

可以看到Sequence类是线程安全的,在MultiProducerSequencer 多个生产者的情况下必须要保障线程安全的.


但是说了这么多,感觉disruptor不可能会出现多个生产者.为什么呢.
在RingBuffer的构造函数中只能传入一个Sequencer对象,一个对象怎么多个生产者.
而且Sequencer不是线程类,完全没办法多线程.
难道是我哪里没看明白吗?

猜你喜欢

转载自huangyunbin.iteye.com/blog/1944344