Netty技术细节源码分析-MpscLinkedQueue队列原理分析

本文的github地址:点此

该文所涉及的netty源码版本为4.1.6。

MpscLinkedQueue是什么

在Netty的核心中的核心成员NioEventLoop中,其中任务队列的实现taskQueue便是MpscLinkedQueue。MpscLinkedQueue是Netty所实现的一个基于多生产者单消费者的无锁队列,针对NioEventLoop中任务队列的特点,其单消费者的场景在一开始就避免了从队列中取数据时加锁的必要,而其最精妙的地方便是在多生产者并发从队列中添加数据的时候也没有加锁,达到Netty所期望的高性能实现。这是如何实现的?

MpscLinkedQueue无锁并发线程安全写入原理

MpscLinkedQueue对于尾结点的维护

首先,MpscLinkedQueue继承自AtomicReference,也就是说MpscLinkedQueue通过继承自AtomicReference的方式,显式地维护了一个提供原子读写能力的变量value。而在MpscLinkedQueue中,这个value是其内部维护的队列的尾结点。

MpscLinkedQueue对于头结点的维护

而后,来看MpscLinkedQueue的构造方法。

    MpscLinkedQueue() {
        MpscLinkedQueueNode<E> tombstone = new DefaultNode<E>(null);
        headRef = new FullyPaddedReference<MpscLinkedQueueNode<E>>();
        headRef.set(tombstone);
        setTail(tombstone);
    }

在MpscLinkedQueue中,维护着headRef头结点字段,其队列内部节点的实现是一个MpscLinkedQueueNode。MpscLinkedQueueNode是一个除了存放具体队列元素外只有next字段的节点,也就是说,MpscLinkedQueue的队列是单向的。在构造方法的最后,通过setTail()方法的,将MpscLinkedQueue的尾结点字段value也设置为头结点。MpscLinkedQueue的头结点字段headRef的存在可以方便后续直接从头结点开始的队列操作,消费者可以简单判断头尾节点是否相等来确认队列中是否有元素可以消费。

MpscLinkedQueue如何做到线程安全的无锁加入

    @Override
    @SuppressWarnings("unchecked")
    public boolean offer(E value) {
        if (value == null) {
            throw new NullPointerException("value");
        }

        final MpscLinkedQueueNode<E> newTail;
        if (value instanceof MpscLinkedQueueNode) {
            newTail = (MpscLinkedQueueNode<E>) value;
            newTail.setNext(null);
        } else {
            newTail = new DefaultNode<E>(value);
        }

        MpscLinkedQueueNode<E> oldTail = replaceTail(newTail);
        oldTail.setNext(newTail);
        return true;
    }

    private MpscLinkedQueueNode<E> replaceTail(MpscLinkedQueueNode<E> node) {
        return getAndSet(node);
    }

MpscLinkedQueue的offer()方法很简短,但是恰恰就是整个添加队列元素加入的流程,当元素被加入的时候,首先判断加入的元素是否是MpscLinkedQueueNode,如果不是则进行封装。之后便是整个操作的重点:

  • 通过replaceTail()方法,将当前被加入的节点通过AtomicReference所提供的getAndSet()方法将其设为队列的尾结点,并返回先前的尾结点。这次操作由UNSAFE的CAS来保证操作的原子性。
  • 之后将之前的尾结点的next指向新加入的节点,本次加入宣告结束。
    整个操作就到此结束,这里可以看出,MpscLinkedQueue利用了AtomicReference底层UNSAFE的能力,通过CAS确保新设置进入value的节点必定能够和原先的节点达成一个且唯一的联系,那么只需要自顶向下不断通过将这个联系变成引用,那么一条队列便形成了。由于其实现是链表而不是数组,也就没有涉及到资源的竞争,在不加锁的前提下其队列顺序可能不会严格按照加入顺序,但这在当前场景下并不是问题。在这个前提,高并发的插入场景下,每个新进入的新节点都将获取原尾位置value上的节点,而自身将会被设置为其后驱节点重新放到尾结点位置上,CAS在不加锁的前提下保证了前后节点对应关系的唯一性,完成了并发条件下不加锁的线程安全写入。

MpscLinkedQueue不支持remove()

在MpscLinkedQueue中,是不支持remove()的方法去从队列中移除任意一个元素的。原因很简单,消费者和生产者是无锁的,消费者可以通过比较队首和队尾元素是否一致来保证线程安全地从队首取数据,但是remove()从队列中任意位置修改数据是线程不安全的,主要体现在移除队尾元素可能会导致正在加入的新元素被丢弃。

MpscLinkedQueue另外的实现细节

  • MpscLinkedQueue中的头节点被通过FullyPaddedReference封装。其内部前后分别填充56字节和64字节来进行填充以避免伪共享导致的性能损耗,使得其头结点可以高效被访问。关于伪共享的相关知识可以通过搜索引擎进行查询。
  • MpscLinkedQueue在消费者消费数据后,当将下一个节点设置为头结点的时候,并不是直接进行赋值,而是通过UNSAFE来根据偏移量赋值,这样做将略微提高性能,主要是内存屏障storestrore和loadstrore之间的性能差异。
相关推荐
<p> 欢迎参加英特尔® OpenVINO™工具套件初级课程 !本课程面向零基础学员,将从AI的基本概念开始,介绍人工智能与视觉应用的相关知识,并且帮助您快速理解英特尔® OpenVINO™工具套件的基本概念以及应用场景。整个课程包含了视频的处理,深度学习的相关知识,人工智能应用的推理加速,以及英特尔® OpenVINO™工具套件的Demo演示。通过本课程的学习,将帮助您快速上手计算机视觉的基本知识和英特尔® OpenVINO™ 工具套件的相关概念。 </p> <p> 为保证您顺利收听课程参与测试获取证书,还请您于<strong>电脑端</strong>进行课程收听学习! </p> <p> 为了便于您更好的学习本次课程,推荐您免费<strong>下载英特尔® OpenVINO™工具套件</strong>,下载地址:https://t.csdnimg.cn/yOf5 </p> <p> 收听课程并完成章节测试,可获得本课程<strong>专属定制证书</strong>,还可参与<strong>福利抽奖</strong>,活动详情:https://bss.csdn.net/m/topic/intel_openvino </p> <p> 8月1日-9月30日,学习完成【初级课程】的小伙伴,可以<span style="color:#FF0000;"><strong>免费学习【中级课程】</strong></span>,中级课程免费学习优惠券将在学完初级课程后的7个工作日内发送至您的账户,您可以在:<a href="https://i.csdn.net/#/wallet/coupon">https://i.csdn.net/#/wallet/coupon</a>查询优惠券情况,请大家报名初级课程后尽快学习哦~ </p> <p> <span style="font-size:12px;">请注意:点击报名即表示您确认您已年满18周岁,并且同意CSDN基于商务需求收集并使用您的个人信息,用于注册OpenVINO™工具套件及其课程。CSDN和英特尔会为您定制最新的科学技术和行业信息,将通过邮件或者短信的形式推送给您,您也可以随时取消订阅不再从CSDN或Intel接收此类信息。 查看更多详细信息请点击CSDN“<a href="https://passport.csdn.net/service">用户服务协议</a>”,英特尔“<a href="https://www.intel.cn/content/www/cn/zh/privacy/intel-privacy-notice.html?_ga=2.83783126.1562103805.1560759984-1414337906.1552367839&elq_cid=1761146&erpm_id=7141654/privacy/us/en/">隐私声明</a>”和“<a href="https://www.intel.cn/content/www/cn/zh/legal/terms-of-use.html?_ga=2.84823001.1188745750.1560759986-1414337906.1552367839&elq_cid=1761146&erpm_id=7141654/privacy/us/en/">使用条款</a>”。</span> </p> <p> <br /> </p>
<p> <br /> </p> <p> <br /> </p> <p> <br /> </p> <p> <b><span style="background-color:#FFE500;">【超实用课程内容】</span></b> </p> <p> <span>本课程根据实际开发中总结出来的一些学习思路,从零开始详细讲解</span><span>Flutter</span><span>的基础知识点。从简到难,从浅入深,逐步带领大家了解</span><span>Flutter</span><span>,熟悉</span><span>Flutter</span><span>的组成部分,并且带领大家学习如何使用</span><span>Flutter</span><span>实现</span><span>UI</span><span>功能编写。通过对本视频的学习,你将会掌握</span><span>Flutter</span><span>常用组件和常用布局构建复杂布局、</span><span>Flutter</span><span>路由导航实现多页面构建和交互、</span><span>Flutetr</span><span>手势处理和动画实现动态交互效果,以及如何使用音视频、图片、文字、字体等资源。除此之外,你还可以收获每一章节遇到的重难点问题的解决方案。</span> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <b><span style="background-color:#FFE500;">【课程如何观看?】</span></b> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> PC端:<a href="https://edu.csdn.net/course/detail/26277"></a><a href="https://edu.csdn.net/course/detail/26150"></a><a href="https://edu.csdn.net/course/detail/26150"></a><a href="https://edu.csdn.net/course/detail/27286"></a><a href="https://edu.csdn.net/course/detail/26858"></a><a href="https://edu.csdn.net/course/detail/26227">https://edu.csdn.net/course/detail/26227</a> </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 移动端:CSDN 学院APP(注意不是CSDN APP哦) </p> <p style="font-family:Helvetica;color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 本课程为录播课,课程永久有效观看时长,大家可以抓紧时间学习后一起讨论哦~ </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <strong><span style="background-color:#FFE500;">【学员专享增值服务】</span></strong> </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> <b>源码开放</b> </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 课件、课程案例代码完全开放给你,你可以根据所学知识,自行修改、优化 </p> <p class="ql-long-24357476" style="font-family:"color:#3A4151;font-size:14px;background-color:#FFFFFF;"> 下载方式:电脑登录<a href="https://edu.csdn.net/course/detail/26277"></a><a href="https://edu.csdn.net/course/detail/26150"></a><a href="https://edu.csdn.net/course/detail/27286"></a><a href="https://edu.csdn.net/course/detail/26858"></a><a href="https://edu.csdn.net/course/detail/26227">https://edu.csdn.net/course/detail/26227</a>,点击右下方课程资料、代码、课件等打包下载 </p> <p> <br /> </p>
©️2020 CSDN 皮肤主题: 游动-白 设计师:白松林 返回首页