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

Condition源码解读(二)

本章我们继续将Condition的最后一个方法signal方法,如果前面没有看过的可以点击LockSupport与Condition解析来看看Condition解读的前半部分。

signal方法:

        public final void signal() {if (!AbstractQueuedLongSynchronizer.this.isHeldExclusively()) {throw new IllegalMonitorStateException();} else {Node var1 = this.firstWaiter;if (var1 != null) {this.doSignal(var1);}}}

signal方法的主要作用就是将线程从Condition队列中唤醒,前面已经讲述过在Condtion的子类ConditionObject内部通过链表来维护整个Condtion队列,并且含有两个属性firstWaiter和lastWaiter分别表示队列头和队列尾部,分析方法首先进行检查当前线程是否持有独占锁。目的是保证持有锁的线程才能调用signal方法来唤醒线程,通过判断之后开始从Condition队列中取出队首线程,随后开始调用doSignal方法来唤醒线程

        private void doSignal(Node var1) {do {if ((this.firstWaiter = var1.nextWaiter) == null) {this.lastWaiter = null;}var1.nextWaiter = null;} while(!AbstractQueuedLongSynchronizer.this.transferForSignal(var1) && (var1 = this.firstWaiter) != null);}

在dosignal中首先将后面的node设置为链表头部,如果后续没有node则将尾链表置为null。

同时调用transferForSignal(first)尝试将节点转移到同步队列,如果转移失败(返回false)且队列还有节点(firstWaiter != null),继续处理下一个节点。

下面我们来看看transferForSignal方法是如何进行转移的。

 final boolean transferForSignal(Node var1) {if (!compareAndSetWaitStatus(var1, -2, 0)) {return false;} else {Node var2 = this.enq(var1);int var3 = var2.waitStatus;if (var3 > 0 || !compareAndSetWaitStatus(var2, var3, -1)) {LockSupport.unpark(var1.thread);}return true;}}

首先进行状态位的CAS设置,如果无法设置表明状态已经改变了直接返回false,表示无法入队。

之后进行入队enq操作(内部是一个循环不断的CAS操作保证能入队)入队完毕之后则查看当前节点状态如果还是阻塞状态则直接调用unpark来唤醒当前线程。

1. 先判断当前线程是否持有当前锁没有则抛出异常

2. 取出Condition队列中的一个首节点尝试入队和唤醒操作

3.失败则再次循环从队伍中取出节点

4.在尝试入队的方法总首先会判断状态值是否符合不符合则直接返回false,符合则会通过CAS循环入队操作,最后判断状态是否为阻塞,为阻塞则直接调用unpark方法进行唤醒操作。

至此Condtion的两个方法已经介绍完毕。

总结:

await方法:

signal方法:

设计精髓

  1. 双队列分离:条件队列(等待条件)与同步队列(竞争锁)分离

  2. 状态驱动waitStatus 精确控制节点生命周期

  3. 无锁算法:CAS 操作保证线程安全

  4. 协作式唤醒:前驱节点负责唤醒后继

  5. 资源继承:await() 返回时自动恢复原始锁状态

典型应用场景

  1. 生产者-消费者:不同条件控制队列空/满

  2. 线程池任务调度:工作线程等待任务到达

  3. 资源池管理:连接可用性通知

  4. 屏障实现:所有线程到达后同时释放

  5. 状态机转换:特定状态变更触发操作

http://www.xdnf.cn/news/689419.html

相关文章:

  • 4.8.2 利用Spark SQL计算总分与平均分
  • Flink 核心机制与源码剖析系列
  • spark- ResultStage 和 ShuffleMapStage介绍
  • 力扣HOT100之回溯:51. N 皇后
  • 电脑长期不关机会怎样?
  • 「Python教案」通用序列操作
  • 股指期货的基差跟升贴水概念
  • 力扣-找到字符串中所有字母异位符
  • JDBC+HTML+AJAX实现登陆和单表的CRUD
  • 互联网大厂Java求职面试:AI大模型推理服务性能优化与向量数据库分布式检索
  • linux 性能优化-内存
  • windows安装启动elasticsearch
  • Linux之高效文本编辑利器 —— vim
  • 家用热水器用户行为分析与事件识别
  • 微信小程序页面嵌套web-view点击系统导航返回时进行弹窗处理
  • nt!CcGetVacbMiss函数分析之设置好nt!_VACB然后调用函数nt!SetVacb
  • LiveWallpaperMacOS:让你的 Mac 桌面动起来
  • Mac完美终端(iterm2 + oh my zash + tmux+ControlMaster)
  • Axure项目实战:运输统计页引入echarts实现高保真设计(JS代码ctrl+c ctrl+v懂得来)
  • OpenHarmony定制系统组合按键(二)
  • Pytest 是什么
  • 进阶知识:Selenium底层原理深度解析
  • Grafana-Gauge仪表盘
  • 5.28 后端面经
  • docker部署redis mysql nacos seata rabbitmq minio onlyoffice nginx实战
  • 20250528-C#知识:枚举
  • 20250528-C#知识:结构体
  • C# Socket对象创建方式详解
  • C接口 中文字符问题
  • 针对C++开发工具推荐及分析(涵盖IDE、编译器、调试工具和辅助工具)