当前位置: 首页 > news >正文

AQS 为什么要使用双向链表?

双向链表

双向链表的特点是它有两个指针,一个指针指向前置节点,一个指针指向后继节点。所以,双向链表可以支持 常量 O(1) 时间复杂度的情况下找到前驱结点,基于这样的特点。双向链表在插入和删除操作的时候,要比单向链表简单、高效。

AQS使用双向链表

因此,从双向链表的特性来看,我认为 AQS 使用双向链表有三个方面的考虑:
第一个方面,没有竞争到锁的线程加入到阻塞队列,并且阻塞等待的前提是,当前线程所在节点的前置节点是正常状态,这样设计是为了避免链表中存在异常线程导致无法唤醒后续线程的问题(如图)所以线程阻塞之前需要判断前置节点的状态,如果没有指针指向前置节点,就需要从 head 节点开始遍历,性能非常低。

第二个方面,在 Lock 接口里面有一个,lockInterruptibly()方法,这个方法表示处于锁阻塞的线程允许被中断。也就是说,没有竞争到锁的线程加入到同步队列等待以后,是允许外部线程通过interrupt()方法触发唤醒并中断的。这个时候,被中断的线程的状态会修改成 CANCELLED。(如图)被标记为 CANCELLED 状态的线程,是不需要去竞争锁的,但是它仍然存在于双向链表里面。意味着在后续的锁竞争中,需要把这个节点从链表里面移除,否则会导致锁阻塞的线程无法被正常唤醒。在这种情况下,如果是单向链表,就需要从 Head 节点开始往下逐个遍历,找到并移除异常状态的节点。同样效率也比较低,还会导致锁唤醒的操作和遍历操作之间的竞争

第三个方面,为了避免线程阻塞和唤醒的开销,所以刚加入到链表的线程,首先会通过自旋的方式尝试去竞争锁。但是实际上按照公平锁的设计,只有头节点的下一个节点才有必要去竞争锁,后续的节点竞争锁的意义不大。否则,就会造成羊群效应,也就是大量的线程在阻塞之前尝试去竞争锁带来比较大的性能开销。所以,(如图)为了避免这个问题,加入到链表中的节点在尝试竞争锁之前,需要判断前置节点是不是头节点,如果不是头节点,就没必要再去触发锁竞争的动作。所以这里会涉及到前置节点的查找,如果是单向链表,那么这个功能的实现会非常复杂。

相关文章:

  • Centos7 安装nvidia显卡驱动
  • 比较3个结构之间的关系
  • 2011-2021年“第四期”数字普惠金融指数与上市公司匹配(根据省份匹配)/上市公司数字金融指数匹配
  • WordPress主题模板 大前端D8 5.1版本完整开源版源码简洁大气多功能配置
  • Kotlin 使用@BindingAdapter编译出错
  • C++数据结构X篇_21_插入排序(稳定的排序)
  • WordPress(7)配置邮箱发送功能
  • C/S架构学习之使用epoll实现TCP特大型并发服务器
  • 【Java系列】LinkedList
  • requirements.txt用法你真的清楚吗
  • 1819_ChibiOS的互斥信号与条件变量
  • Idea Debug断点太多 启动太慢
  • 【易售小程序项目】后端部署、Uniapp项目Web部署
  • electron27+react18集成搭建跨平台应用|electron窗口多开
  • 皮卡丘RCE靶场通关攻略
  • E-HPC支持多队列管理和自动伸缩
  • ES6 ...操作符
  • Eureka 2.0 开源流产,真的对你影响很大吗?
  • HTML5新特性总结
  • java8 Stream Pipelines 浅析
  • JS题目及答案整理
  • Mac 鼠须管 Rime 输入法 安装五笔输入法 教程
  • PyCharm搭建GO开发环境(GO语言学习第1课)
  • python3 使用 asyncio 代替线程
  • Python实现BT种子转化为磁力链接【实战】
  • vue2.0一起在懵逼的海洋里越陷越深(四)
  • Vue学习第二天
  • 开发基于以太坊智能合约的DApp
  • 开发了一款写作软件(OSX,Windows),附带Electron开发指南
  • 前端工程化(Gulp、Webpack)-webpack
  • 用 vue 组件自定义 v-model, 实现一个 Tab 组件。
  • 浅谈sql中的in与not in,exists与not exists的区别
  • 容器镜像
  • ​ssh免密码登录设置及问题总结
  • #include
  • #vue3 实现前端下载excel文件模板功能
  • $.ajax中的eval及dataType
  • ${factoryList }后面有空格不影响
  • $jQuery 重写Alert样式方法
  • (1/2) 为了理解 UWP 的启动流程,我从零开始创建了一个 UWP 程序
  • (5)STL算法之复制
  • (echarts)echarts使用时重新加载数据之前的数据存留在图上的问题
  • (PWM呼吸灯)合泰开发板HT66F2390-----点灯大师
  • (论文阅读32/100)Flowing convnets for human pose estimation in videos
  • (提供数据集下载)基于大语言模型LangChain与ChatGLM3-6B本地知识库调优:数据集优化、参数调整、Prompt提示词优化实战
  • .NET Core 成都线下面基会拉开序幕
  • .net core 控制台应用程序读取配置文件app.config
  • .NET NPOI导出Excel详解
  • .NET单元测试
  • .Net的C#语言取月份数值对应的MonthName值
  • ?php echo $logosrc[0];?,如何在一行中显示logo和标题?
  • @PreAuthorize注解
  • @TableId注解详细介绍 mybaits 实体类主键注解
  • [ 第一章] JavaScript 简史
  • [2021ICPC济南 L] Strange Series (Bell 数 多项式exp)