DISRUPT 快的原因

DISRUPT  快的原因


标签(空格分隔): 队列 生产者 消费者


---
在我们开发过程中经常使用的就是arrayBlockingqueue,再看《亿级流量架构》的时候发现还有一个更好用的东西  ===》Disruptor(无锁并发)


我看了一下官网的介绍,还有并发编程网中的翻文 总结了以下几点为什么快的原因




##Disruptor根本就不用锁


    disruptor使用的是一个ringBuffer环形的数组结构,而且有一个容易预测的访问模式。(译者注:数组内元素的内存地址的连续性存储的)。这是对CPU缓存友好的—也就是说,在硬件级别,数组中的元素是会被预加载的,因此在ringbuffer当中,cpu无需时不时去主存加载数组中的下一个元素。(校对注:因为只要一个元素被加载到缓存行,其他相邻的几个元素也会被加载进同一个缓存行)它不像队列一样使用tail和head指定位置,它只需一个指向下一个位置点的序号,并且获取数据的时候也是无锁的
    
    其次,你可以为数组预先分配内存,使得数组对象一直存在(除非程序终止)。这就意味着不需要花大量的时间用于垃圾回收。此外,不像链表那样,需要为每一个添加到其上面的对象创造节点对象—对应的,当删除节点时,需要执行相应的内存清理操作。
    
![此处输入图片的描述][1]


    取而代之的是,在需要确保操作是线程安全的(特别是,在多生产者的环境下,更新下一个可用的序列号)地方,我们使用CAS(Compare And Swap/Set)操作。这是一个CPU级别的指令,在我的意识中,它的工作方式有点像乐观锁——CPU去更新一个值,但如果想改的值不再是原来的值,操作就失败,因为很明显,有其它操作先改变了这个值。
![此处输入图片的描述][2]


**注意,这可以是CPU的两个不同的核心,但不会是两个独立的CPU。**


    CAS操作比锁消耗资源少的多,因为它们不牵涉操作系统,它们直接在CPU上操作。但它们并非没有代价——在上面的试验中,单线程无锁耗时300ms,单线程有锁耗时10000ms,单线程使用CAS耗时5700ms。所以它比使用锁耗时少,但比不需要考虑竞争的单线程耗时多。




![此处输入图片的描述][3]


##消费者无锁,类似订阅逻辑不用轮训是否有新数据




![此处输入图片的描述][4]


    
    消费者可以调用ConsumerBarrier对象的waitFor()方法,传递它所需要的下一个序号.


    final long availableSeq = consumerBarrier.waitFor(nextSequence);


ConsumerBarrier返回RingBuffer的最大可访问序号——在上面的例子中是12。ConsumerBarrier有一个WaitStrategy方法来决定它如何等待这个序号


consumerBarrier监听了生产者那边的一个Strategy,一旦发现生产者有新数据进来了就通知这个waitStrategy 当然waitStrategy 这个策略有三种。


![此处输入图片的描述][5]


    有助于平缓延迟的峰值了——以前需要逐个节点地询问“我可以拿下一个数据吗?现在可以了么?现在呢?”,消费者(Consumer)现在只需要简单的说“当你拿到的数字比我这个要大的时候请告诉我”,函数返回值会告诉它有多少个新的节点可以读取数据了。因为这些新的节点的确已经写入了数据(Ring Buffer本身的序号已经更新),而且消费者对这些节点的唯一操作是读而不是写,因此访问不用加锁。这太好了,不仅代码实现起来可以更加安全和简单,而且不用加锁使得速度更快。


    另一个好处是——你可以用多个消费者(Consumer)去读同一个RingBuffer ,不需要加锁,也不需要用另外的队列来协调不同的线程(消费者)。这样你可以在Disruptor的协调下实现真正的并发数据处理
 
  
##生产者无锁


![此处输入图片的描述][6]


    生产者也有一个ProducerBarrier,每个生产者都是通过这个是拿下一个可用的位置节点,当然因为是一个环形,如果有消费者消费的慢,比如说消费者消费到3,生产者就不能拿到3之后的位置点进行存入。只会在那里等待。如果最后的消费者都消费到了11位置,那么3到11位置之间的空档,生产就可以拿去存了。这一切位置是否有空余,都是claimStrategy 通知生产者的。


    另外要说的一点就生产者是分两阶段提交的,假如3-11的位置有空余,ProducerBarrier允许多个生产者一起生成然后提交,当然生产者有快,有慢,在最后提交的时候,要按顺序提交,好比说生产者1已经把7位置点的数据都准备好的,生产者2生成6位置数据还没有提交。生产者1就需要等待生产者2提交了再提交。不过这样也算是并发的生产吧。比一个个强的多,是吧




  部分是在并发编程网摘抄下来的,如果越权,联系我删除


  [6om/wp-content/uploads/2013/01/RingBufferReplay.png




  [1]: http://ifeve.com/wp-content/uploads/2013/01/RingBufferInitial.png
  [2]: http://ifeve.com/wp-content/uploads/2013/01/ConcurrencyCAS.png
  [3]: http://ifeve.com/wp-content/uploads/2013/01/RingBufferReplay.png
  [4]: http://ifeve.com/wp-content/uploads/2013/02/Image21.png
  [5]: http://ifeve.com/wp-content/uploads/2013/01/ProducerBatching.png
  [6]: http://ifeve.com/wp-content/uploads/2013/01/ProducerNextEntry.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值