disruptor学习笔记
来源:互联网 发布:软件杂志社官网 编辑:程序博客网 时间:2024/06/07 00:39
Ring Buffer的优势:
1. 内存屏障:volatile
提供与锁类似的语义,但是代码比锁小得多。volatile可以阻止代码重排序,并且值被更新的时候,会导致缓存失效,强制回写到主存中。
2. 伪共享与缓存行
CPU缓存通常一次缓存多个字(32、64或128字节),称为缓存行。如果位于同一个缓存行中的多个变量被不同的线程进行写,由于每次写都有可能刷新主存导致缓存失效,从而导致性能低下,即伪共享。可以使用缓存行填充来阻止共享缓存这种情况的出现,从而提升性能。如:
PaddedLong类,它使用了7个long,加上一个对象头,刚好64个字节。
Sequence类:private final long[] paddedValue = new long[15];
这个类更复杂一些,它的内存结构如下(从学习资料2中转载):
[头部: 8 bytes] 8
[数组长度: 4 bytes] 12
[padding: 4 bytes] 16
[元素1: 8 bytes] 24
[元素2: 8 bytes] 32
[元素3: 8 bytes] 40
[元素4: 8 bytes] 48
[元素5: 8 bytes] 56
[元素6: 8 bytes] 64
[元素7: 8 bytes] 72
[元素8: 8 bytes] 80
[元素9: 8 bytes] 88
[元素10: 8 bytes] 96
[元素11: 8 bytes] 104
[元素12: 8 bytes] 112
[元素13: 8 bytes] 120
[元素14: 8 bytes] 128
[元素15: 8 bytes] 136
Sequence使用了数组中第8个元素。这就意味着,无论在向头对齐还是向尾对齐,这个值总是会在一个单独的缓存行中。
有PaddedLong为什么还要Sequence类呢,主要是因为Java7对对象内存模型做了优化,如果它发现有字段没被使用,就会被优化掉,这时就又出现伪共享了。
见这篇博客:http://mechanical-sympathy.blogspot.com/2011/08/false-sharing-java-7.html
3. CAS:无锁更新
Compare and set,硬件直接支持的指令,ring buffer中通过UnSafe类来实现。
4. 大量的无锁实现(Sequence, PaddedLong等),使用数组存储数据(类似ArrayBlockingQueue),减少GC。
ring buffer整体结构:
一个环形的数组,next:下一个可用的slot。cursor:最近一个被填充的slot。
一个ClaimStrategy用于生产者生产数据时提供判断(当前是否有空闲的slot可以申请到),一个WaitStragety用于消费者消费数据时提供判断(当前是否有数据可以消费)。
其中ClaimStragety和WaitStragety都有针对不同场景的多种不同实现。
ClaimStragety:SingleThreadedClaimStragety,单线程;MultithreadedClaimStragety,多线程。
WaitStragety:
BlockingWaitStragety:使用了锁,实际上只能每个线程轮流来消费了。。。
BusySpinWaitStragety:使用自旋(会非常消耗CPU)
。。。
如何生产数据:
1. 取得当前可用的sequence
ringbuffer.next() ==> claimStragety.incrementAndGet() ==》waitForFreeSlotAt(依赖于消费者的sequence,即gatingSequences,每一个sequence都被一个BatchEventProcessor引用,代表最近消费的slot)。
看多个消费者中,消费得最慢的那个(即sequence最小的)如果minSequence > sequence-BufferSize,表示生产者和消费者重叠了,就需要等待。
2. 取得该sequence上的数据对象,填充对象
3. 发布数据。
claimStragety.serialisePublishing(sequence, cursor, batchSize);
waitStragety.signalAllWhenBlocking();
注意这里sequence是long的,cursor是Sequence类型的,位于Sequencer类中(RingBuffer的基类),是ring buffer维护的全局变量。
消费数据的时候,也不使用claimStragety。
生产者和消费者相对独立,只通过ring buffer来交互。这样相对地减少了耦合。
附几个disruptor的学习资料:
1. http://ifeve.com/disruptor/ 这是关于disruptor的入门文章。
2. http://www.dongsm.cn/disruptor%E4%BB%A3%E7%A0%81%E5%88%86%E6%9E%90-%E5%8F%96%E6%A8%A1%E7%9A%84%E4%BC%98%E5%8C%96/ 这里关于disruptor写了一系列,相对还比较深入。
- disruptor学习笔记
- disruptor 笔记
- disruptor学习
- Disruptor笔记(二)-测试
- Disruptor笔记(五)-FAQ
- Disruptor笔记(二)-测试
- Disruptor笔记(五)-FAQ
- Disruptor使用笔记
- Disruptor个人笔记(一)
- Disruptor源码阅读笔记
- Disruptor学习总结(二):Disruptor分析
- Disruptor学习----综述
- Disruptor学习地址
- Disruptor笔记(一)-预备知识
- Disruptor笔记(三)-处理模式
- Disruptor笔记(一)-预备知识
- Disruptor笔记(三)-处理模式
- Disruptor
- Software
- 括号的匹配(简单)
- 去掉Eclipse RCP中的多余默认按钮
- UVA 662 Fast Food(dp)
- BNU4210
- disruptor学习笔记
- 将Request.QueryString获得的值转换为INT
- 根据数据库表名获取列名
- 新浪微博API Oauth2.0 认证。。。
- 解析XML文件的具体案例
- hdu-2043-密码
- 再谈webview漏洞
- java中的数学函数
- 根据年月日计算周日期