【JUC】浅析ConcurrentLinkedQueue

news2024/9/23 12:04:23

【JUC】浅析ConcurrentLinkedQueue

文章目录

  • 【JUC】浅析ConcurrentLinkedQueue
    • 一、前言
    • 二、ConcurrentLinkedQueue的结构
    • 三、入队列
      • 3.1、入队列的过程
      • 3.2、定位尾节点
      • 3.3、设置入队节点为尾节点
      • 3.4、HOPS的设计意图
    • 四、出队列

一、前言

在并发编程中,有时候需要使用线程安全的队列。如果要实现一个线程安全的队列有两种方式:一种是使用阻塞算法,另一种是使用非阻塞算法。使用阻塞算法的队列可以用一个锁(入队和出队用同一把锁)或两个锁(入队和出队用不同的锁)等方式来实现。非阻塞的实现方式则可以使用循环CAS的方式来实现。本节让我们一起来研究一下DougLea是如何使用非阻塞的方式来实现线程安全队列ConcurrentLinkedQueue的,相信从大师身上我们能学到不少并发编程的技巧。

ConcurrentLinkedQueue是一个基于链接节点的无界线程安全队列,它采用先进先出的规则对节点进行排序,当我们添加一个元素的时候,它会添加到队列的尾部;当我们获取一个元素时,它会返回队列头部的元素。它采用了“wait-free”算法(即CAS算法)来实现,该算法在Michael&Scott算法上进行了一些修改。

二、ConcurrentLinkedQueue的结构

通过ConcurrentLinkedQueue的类图来分析一下它的结构

image-20230504194016384

ConcurrentLinkedQueue由head节点和tail节点组成,每个节点(Node)由节点元素(item)和指向下一个节点(next)的引用组成,节点与节点之间就是通过这个next关联起来,从而组成一张链表结构的队列。默认情况下head节点存储的元素为空,tail节点等于head节点。

image-20230504194048249

三、入队列

3.1、入队列的过程

入队列就是将入队节点添加到队列的尾部。

为了方便理解入队时队列的变化,以及head节点和tail节点的变化,这里以一个示例来展开介绍。假设我们想在一个队列中依次插入4个节点,为了帮助大家理解,每添加一个节点就做了一个队列的快照图。

image-20230504194304259

  • 加元素1。队列更新head节点的next节点为元素1节点。又因为tail节点默认情况下等于head节点,所以它们的next节点都指向元素1节点。
  • 加元素2。队列首先设置元素1节点的next节点为元素2节点,然后更新tail节点指向元素2节点。
  • 加元素3,设置tail节点的next节点为元素3节点。
  • 加元素4,设置元素3的next节点为元素4节点,然后将tail节点指向元素4节点。

通过调试入队过程并观察head节点和tail节点的变化,发现入队主要做两件事情:

  • 第一是将入队节点设置成当前队列尾节点的下一个节点;
  • 第二是更新tail节点,如果tail节点的next节点不为空,则将入队节点设置成tail节点,如果tail节点的next节点为空,则将入队节点设置成tail的next节点,所以tail节点不总是尾节点(理解这一点对于我们研究源码会非常有帮助)。

通过对上面的分析,我们从单线程入队的角度理解了入队过程,但是多个线程同时进行入队的情况就变得更加复杂了,因为可能会出现其他线程插队的情况。如果有一个线程正在入队,那么它必须先获取尾节点,然后设置尾节点的下一个节点为入队节点,但这时可能有另外一个线程插队了,那么队列的尾节点就会发生变化,这时当前线程要暂停入队操作,然后重新获取尾节点。让我们再通过源码来详细分析一下它是如何使用CAS算法来入队的。

image-20230504194714652

从源代码角度来看,整个入队过程主要做两件事情:第一是定位出尾节点;第二是使用CAS算法将入队节点设置成尾节点的next节点,如不成功则重试。

3.2、定位尾节点

tail节点并不总是尾节点,所以每次入队都必须先通过tail节点来找到尾节点。尾节点可能是tail节点,也可能是tail节点的next节点。代码中循环体中的第一个if就是判断tail是否有next节点,有则表示next节点可能是尾节点。获取tail节点的next节点需要注意的是p节点等于p的next节点的情况,只有一种可能就是p节点和p的next节点都等于空,表示这个队列刚初始化,正准备添加节点,所以需要返回head节点。获取p节点的next节点代码如下。

image-20230504195021525

3.3、设置入队节点为尾节点

p.casNext(null,n)方法用于将入队节点设置为当前队列尾节点的next节点,如果p是null,表示p是当前队列的尾节点,如果不为null,表示有其他线程更新了尾节点,则需要重新获取当前队列的尾节点。

3.4、HOPS的设计意图

上面分析过对于先进先出的队列入队所要做的事情是将入队节点设置成尾节点,doug lea写的代码和逻辑还是稍微有点复杂。那么,我用以下方式来实现是否可行?

image-20230504195155563

让tail节点永远作为队列的尾节点,这样实现代码量非常少,而且逻辑清晰和易懂。但是,这么做有个缺点,每次都需要使用循环CAS更新tail节点。

如果能减少CAS更新tail节点的次数,就能提高入队的效率,所以doug lea使用hops变量来控制并减少tail节点的更新频率,并不是每次节点入队后都将tail节点更新成尾节点,而是当tail节点和尾节点的距离大于等于常量HOPS的值(默认等于1)时才更新tail节点,tail和尾节点的距离越长,使用CAS更新tail节点的次数就会越少,但是距离越长带来的负面效果就是每次入队时定位尾节点的时间就越长,因为循环体需要多循环一次来定位出尾节点,但是这样仍然能提高入队的效率。

因为从本质上来看它通过增加对volatile变量的读操作来减少对volatile变量的写操作,而对volatile变量的写操作开销要远远大于读操作,所以入队效率会有所提升。

image-20230504195309790

四、出队列

出队列的就是从队列里返回一个节点元素,并清空该节点对元素的引用。让我们通过每个节点出队的快照来观察一下head节点的变化。

image-20230504195346029

从图中可知,并不是每次出队时都更新head节点,当head节点里有元素时,直接弹出head节点里的元素,而不会更新head节点。只有当head节点里没有元素时,出队操作才会更新head节点。

这种做法也是通过hops变量来减少使用CAS更新head节点的消耗,从而提高出队效率。让我们再通过源码来深入分析下出队过程。

image-20230504195455878

首先获取头节点的元素,然后判断头节点元素是否为空,如果为空,表示另外一个线程已经进行了一次出队操作将该节点的元素取走,如果不为空,则使用CAS的方式将头节点的引用设置成null,如果CAS成功,则直接返回头节点的元素,如果不成功,表示另外一个线程已经进行了一次出队操作更新了head节点,导致元素发生了变化,需要重新获取头节点。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/505686.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

本文主要介绍在VMware虚拟机里面安装windows sever 2012 R2并且配置hyper-V的过程,此外还涵盖出现问题的解决方案。

系列文章目录 Windows xp 在VMware虚拟机上面安装的详细步骤_xp系统虚拟机 虚拟机VMware里面安装Windows sever 2003版本详细教程 Windows配置虚拟网络 文章目录 系列文章目录 前言 一、配置的前提条件 1.1、实验环境 1.2、资源分享 二、安装教程 2.1、新建windows …

不同设备如何统一语言编程平台高效开发?本文为你揭秘

原文:不同设备如何统一语言编程平台高效开发?本文为你揭秘,点击链接查看更多技术内容。 随着数字化时代的发展,手机、平板、PC、电视、智能手表、车机等智能设备的普及率越来越高,但不同设备往往搭载了不同的操作系统。…

Word控件Spire.Doc 【文本框】教程(1):如何在 C 语言中设置 Word 文本框的内部边距

Spire.Doc for .NET是一款专门对 Word 文档进行操作的 .NET 类库。在于帮助开发人员无需安装 Microsoft Word情况下,轻松快捷高效地创建、编辑、转换和打印 Microsoft Word 文档。拥有近10年专业开发经验Spire系列办公文档开发工具,专注于创建、编辑、转…

改写中文句子的软件-修改文章句子的软件

免费语句改写软件 您是否在写博客、新闻稿或者其他需要大量文本的场合中觉得无从下手?您是否为修改一段语句上耗费大量时间感到困扰?如果您有这样的烦恼,那么我向您介绍我们的免费语句改写软件,可以帮助您快速批量语句改写&#x…

“AI代劳”,跨域赋能“智慧企业”

随着全球数字信息化的到来,各大新兴行业企业也逐渐意识到“智慧化”转型的重要性,但目前仍有不少企业在面临着人力成本高、运营管理效率低、营销获客效果差、数据分析能力薄弱等瓶颈,那么,处于这些瓶颈期的企业该如何实现“智慧化…

Vue-弹层显示样式

弹层显示样式1 1.先将左侧样式写 <template><div classhome-category><ul class"menu"><li v-for"i in 10" :key"i"><RouterLink to"/">居家</RouterLink><RouterLink to"/">洗…

pd电源测试-PD电源自动测试系统ATECLOUD-Power

PD电源测试是一种重要的电源测试方法&#xff0c;采用该方法可以更加全面、详细地评估各种电子产品和设备的性能和安全性。本文将阐述PD电源测试的基本原理、测试对象以及测试的应用价值。 首先&#xff0c;PD电源测试的基本原理是通过对电压、电流、功率等重要指标进行测试评…

无论是企业或个人,你知道数据泄露有多严重吗?

现代科技的发展使我们的隐私越来越容易受到侵犯&#xff0c;互联网、社交媒体和智能手机等技术使我们的信息变得更加易于访问和共享。此外商业公司和机构也积极收集和利用我们的个人数据&#xff0c;这些公司和机构可能利用我们的数据来推销产品和服务&#xff0c;或者在不经过…

励志长篇小说《周兴和》书连载之二饥饿寒冷童年

饥饿寒冷童年梦 兴和至今也记得&#xff0c;这年冬天特别冷。 那一天&#xff0c;放了学的小兴和背着书篼&#xff0c;又冷又饿地从毛公乡小学出来&#xff0c;艰难地爬上了回家的那条山道。他已一天没吃东西了&#xff0c;肚皮早就饿得贴着脊梁骨了。爬上一个小山坡&#xff…

(六)实现好友管理:教你如何在即时通信系统中添加好友

文章目录 一、引言1.1 即时通信系统中用户增加好友功能的重要性和应用场景1.2 TCP连接传输用户增加好友请求的基本原理 二、实现用户增加好友功能2.1 实现用户好友列表的展示和管理2.1.1 使用QListWidgetItem控件展示好友列表客户端关键代码展示服务端关键代码展示 三、效果展示…

深度学习笔记之梯度下降、反向传播与内置优化器

文章目录 1. 梯度下降法2. 反向传播算法3. PyTorch内置的优化器3.1 SGD优化器3.2 RMSprop优化器3.3 Adam优化器 1. 梯度下降法 笔者往期的机器学习笔记&#xff1a; 机器学习之梯度下降算法 梯度下降法是一种致力于找到函数极值点的算法。 所谓“训练”或“学习”就是改进…

2023年跨境电商必读:海外网红营销的4大雷区及应对策略

随着跨境电商的快速发展和海外网红的普及&#xff0c;海外网红营销已成为越来越多跨境电商企业推广品牌的必备手段。然而&#xff0c;在进行海外网红营销时&#xff0c;企业需要注意一系列雷区&#xff0c;以确保营销的有效性和可持续性。本文Nox聚星将和大家探讨2023年跨境电商…

AI自动写文章_免费在线原创文章生成器

自动写文章生成器 自动写文章生成器是一种利用人工智能和自然语言处理技术&#xff0c;帮助用户快速生成文章的工具。该软件可以根据用户的需求和选择&#xff0c;自动生成符合要求的文章&#xff0c;无需手动编写和修改。 自动写文章生成器的主要功能包括以下几个方面&#…

(三)打造华丽的即时通信系统主界面,让你的聊天体验更有质感

文章目录 一、引言1、即时通信系统的基本概念和应用场景2、Qt框架在实现即时通信系统中的应用 二、主界面设计2.1 界面设计的基本要求2.2 主界面的设计 三、通信功能实现3.1 通信协议的选择3.1.1 TCP协议和UDP协议的优缺点比较3.1.2选择何种协议进行即时通信系统的实现 3.2 通信…

单片机的电子秤方案设计

电子秤是一种利用电子技术实现重量计量的设备&#xff0c;广泛应用于商业、工业、医疗、科学研究等领域。电子秤是一种高精度的计重装置&#xff0c;不仅精度高&#xff0c;而且使用方便、稳定可靠。下面&#xff0c;我们从结构设计、工作原理、功能参数、产品种类四个方面来介…

MyBatis基础知识点总结

MyBatis了解 MyBatis 是什么&#xff1f; MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的持久层框架 MyBatis 避免了几乎所有的 JDBC 代码和手动设置参数以及获取结果集 MyBatis 可以使用简单的XML或注解用于配置和原始映射&#xff0c;将接口和Java的 POJO&#x…

Canvas 2D详解

在我书的第六章中有一个关于MNIST手写数字的例子&#xff0c;当数据集加载完成之后&#xff0c;用户可以在<canvas/>上输入手写数字&#xff0c;点击「预测」按钮之后&#xff0c;浏览器会弹出经模型预测之后的结果&#xff1b;在我书的第九章和第十章中&#xff0c;分别…

2023年宜昌市中等职业学校技能大赛 “网络搭建与应用”竞赛题-2

2023年宜昌市中等职业学校技能大赛 “网络搭建与应用”竞赛题 一、竞赛内容分布 “网络搭建及应用”竞赛共分二个部分&#xff0c;其中&#xff1a; 第一部分&#xff1a;企业网络搭建部署项目&#xff0c;占总分的比例为50%&#xff1b; 第二部分&#xff1a;企业网络服…

第十四届蓝桥杯大赛软件赛省赛(Java 大学A组)

蓝桥杯 2023年省赛真题 Java 大学A组 试题 A: 特殊日期  试题 B: 与或异或 把填空挂上跟大伙对对答案&#xff0c;先把C/C B组的做了。 试题 A: 特殊日期 本题总分&#xff1a;5 分 【问题描述】 记一个日期为 y y \small yy yy 年 m m \small mm mm 月 d d \small dd dd 日…