Distruptor无锁队列实现说明
1、Volatile仅保证线程间读、写立刻可见;且禁用cpu指令顺序优化;
2、Volatile只能用于单cpu指令的操作,如实现Volatile.Read(ref x);或Volatile.Writle(ref x, 10); 即最简单的读取或赋值;不能做x++、if(x>10) x++;等多cpu指令操作;
3、如存在两个cpu同时执行Volatile操作,不保证串行,因仅单cpu指令,读、写都可能提前发生,读到的内容可能是旧值,也可能是新值;读到的内容可理解成是内存地址的瞬间快照;
4、单线程赋值写入(x=1; Volatile.Write(flag))搭配另一线程 Volatile.Read,是它的舒适区;其他复杂场景(如多线程读、多线程写)需引入CAS或锁;
5、对于保护的数据是单调递增或递减场景,多个线程写需配合interlocked.CompareChange判断是否写入成功,不成功继续重试,即可实现线程排队操作;多个线程读取判断,拿到快照数据后和预期数据做比较(单调性很重要),判断是否符合预期;可能读到的数据比预期数据大,则后续处理需执行多次;
6、disruptor环形队列中,多生产者执行逻辑:
1)生产者获取消费者当前消费数据位置;
2)判断当前写入位置是否追上消费位置,如追上,等待并继续判断;
3)可以写入数据后,获取写入位置(当前位置加1);位置数据持续增加,用位运算获取可用环形队列索引;
4)使用Interlocked.CompareExchange尝试修改CurrentWritePos,如被其他线程先行修改过,写入失败,需重复1)-- 4)步骤;如写入成功,则成功占用了这个队列节点,后续可以将数据写入节点,并更新节点最新序号数组;
7、distruptor环形队列中,多消费者执行逻辑:
1)循环判断是否有可用节点;
2)生产者写入成功时,在节点状态数组中,对应节点位置写入最新的序号;
3)消费者找到大于当前位置的序号,得到可消费节点(一或多个);
4)消费一或多个节点数据;
