Condition的await()方法底层源码
一、Condition的await()方法底层源码
以下是 ConditionObject 中 await 方法的源码及其详细分析:
public final void await() throws InterruptedException {
// 判断当前线程是否是中断状态,是就直接给个中断异常
if (Thread.interrupted())
throw new InterruptedException();
// 将调用 await 的线程包装成 Node,添加到 Condition条件队列并返回
Node node = addConditionWaiter();
// 完全释放节点持有的锁,因为其他线程唤醒当前线程的前提是【持有锁】
int savedState = fullyRelease(node);
// 设置打断模式为没有被打断,状态码为 0
int interruptMode = 0;
// 如果该节点还没有转移至 AQS 阻塞队列, park 阻塞,等待进入 AQS阻塞队列
while (!isOnSyncQueue(node)) {
LockSupport.park(this);
// 如果被打断,退出等待队列,对应的 node 【也会被迁移到 AQS阻塞队列】尾部,状态设置为 0
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 逻辑到这说明当前线程退出 Condition条件队列,进入【AQS阻塞队列】
// 尝试枪锁,获取锁成功判断打断模式
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
// node 在Condition条件队列时 如果被外部线程中断唤醒,会加入到 AQS阻塞队列,但是并未设 nextWaiter = null
if (node.nextWaiter != null)
// 清理条件队列内所有已取消的 Node
unlinkCancelledWaiters();
// 条件成立说明挂起期间发生过中断
if (interruptMode != 0)
// 应用打断模式
reportInterruptAfterWait(interruptMode);
}
二、await 方法的详细步骤解析
1、检查线程中断状态
- Thread.interrupted():检查当前线程是否已被中断。如果已被中断,抛出 InterruptedException。
2、创建等待节点
addConditionWaiter():将当前线程封装为一个 Node 节点,并加入到 Condition 的等待队列中。
Condition 的等待队列是一个单向链表,每个节点代表一个等待线程。
新节点会被添加到链表的尾部。
3、释放锁
fullyRelease(node):完全释放与 Condition 关联的锁。
调用 AQS 的 release 方法,释放锁并唤醒后继节点。
保存当前的锁状态(savedState),以便后续重新获取锁。
4、阻塞线程
isOnSyncQueue(node):检查当前节点是否在同步队列中。
如果节点不在同步队列中,调用 LockSupport.park(this) 阻塞当前线程。
线程被阻塞后,会一直等待,直到被其他线程调用 signal 或 signalAll 唤醒,或者被中断。
5、处理中断
checkInterruptWhileWaiting(node):检查线程是否在等待过程中被中断。
如果被中断,返回中断模式(THROW_IE 或 REINTERRUPT)。
THROW_IE:表示在等待过程中被中断,需要抛出 InterruptedException。
REINTERRUPT:表示在唤醒后被中断,需要重新设置中断状态。
6、重新获取锁
acquireQueued(node, savedState):线程被唤醒后,重新尝试获取锁。
如果获取锁成功,返回 true。
如果获取锁失败,线程会继续阻塞,直到获取锁。
7、清理取消的等待节点
unlinkCancelledWaiters():清理等待队列中已取消的节点。
遍历等待队列,移除状态为 CANCELLED 的节点。
8、报告中断状态
reportInterruptAfterWait(interruptMode):根据中断模式处理中断状态。
如果中断模式为 THROW_IE,抛出 InterruptedException。
如果中断模式为 REINTERRUPT,重新设置线程的中断状态。
Condition的await()方法底层源码的更多相关文章
- AspNetCore底层源码剖析(三)IOC
title: AspNetCore底层源码剖析(三)IOC date: 2022-09-21 13:20:01 categories: 后端 tags: - .NET 介绍 每个 ASP.NET Co ...
- Android开发之漫漫长途 Ⅵ——图解Android事件分发机制(深入底层源码)
该文章是一个系列文章,是本人在Android开发的漫漫长途上的一点感想和记录,我会尽量按照先易后难的顺序进行编写该系列.该系列引用了<Android开发艺术探索>以及<深入理解And ...
- 为什么很多类甚者底层源码要implements Serializable ?
为什么很多类甚者底层源码要implements Serializable ? 在碰到异常类RuntimeException时,发现Throwable实现了 Serializable,还有我们平进的ja ...
- List-LinkedList、set集合基础增强底层源码分析
List-LinkedList 作者 : Stanley 罗昊 [转载请注明出处和署名,谢谢!] 继上一章继续讲解,上章内容: List-ArreyLlist集合基础增强底层源码分析:https:// ...
- 从底层源码浅析Mybatis的SqlSessionFactory初始化过程
目录 搭建源码环境 POM依赖 测试SQL Mybatis全局配置文件 UserMapper接口 UserMapper配置 User实体 Main方法 快速进入Debug跟踪 源码分析准备 源码分析 ...
- Java泛型底层源码解析-ArrayList,LinkedList,HashSet和HashMap
声明:以下源代码使用的都是基于JDK1.8_112版本 1. ArrayList源码解析 <1. 集合中存放的依然是对象的引用而不是对象本身,且无法放置原生数据类型,我们需要使用原生数据类型的包 ...
- 2018.11.20 Struts2中对结果处理方式分析&struts2内置的方式底层源码剖析
介绍一下struts2内置帮我们封装好的处理结果方式也就是底层源码分析 这是我们的jar包里面找的位置目录 打开往下拉看到result-type节点 name那一列就是我们的type类型取值 上一篇博 ...
- HashMap和ConcurrentHashMap的区别,HashMap的底层源码
HashMap本质是数组加链表,根据key取得hash值,然后计算出数组下标,如果多个key对应到同一个下标,就用链表串起来,新插入的在前面. ConcurrentHashMap在HashMap的基础 ...
- 总结HashSet以及分析部分底层源码
总结HashSet以及分析部分底层源码 1. HashSet继承的抽象类和实现的接口 继承的抽象类:AbstractSet 实现了Set接口 实现了Cloneable接口 实现了Serializabl ...
- LInkedList总结及部分底层源码分析
LInkedList总结及部分底层源码分析 1. LinkedList的实现与继承关系 继承:AbstractSequentialList 抽象类 实现:List 接口 实现:Deque 接口 实现: ...
随机推荐
- React、Angular、Vue.js三者比较指南
Vue-React-Angular三者区别 1. 基本概念Angular 是一个应用设计框架与开发平台,用于创建高效.复杂.精致的单页面应用. React 是一个用于构建用户界面的 JavaScr ...
- Linux开发帮助参考
在开发Linux系统下面软件时常常需要查阅手册,但是如果你的开发平台不是Linux系统,那你无法丝滑使用man手册,这里推荐一些方便的Linux开发手册. 手册: 在线man手册:Linux Man ...
- 天翼云重磅升级边缘WAF能力,助力企业高效应对Web安全威胁!
"2022年,网络高危漏洞数量同比增长了13%:Q2遭受攻击的API数量月均超过了25万:物联网的普及大大降低了DDoS的攻击成本,大流量攻击指数显著提升:恶意Bot流量仍在持续增长,202 ...
- Django-Admin和第三方插件Xadmin
Admin django内置了一个强大的组件叫Admin,提供给网站管理员快速开发运营后台的管理站点. 站点文档: https://docs.djangoproject.com/zh-hans/2.2 ...
- postman获取时间戳并自动计算token
工作中时常要测试接口,公共请求参数包括id, timestamp, token, token = MD5(id + key + timestamp)并转大写. 每次用外部工具去获取时间戳并计算toke ...
- Kettle - 简介
ETL简介 Kettle简介 transformation 和 job的区别 Kettle 的核心组件 Kettle 特点 Kettle 的目录说明 Kettle 的文件说明 ETL简介 ETL,Ex ...
- BloomFilter详解
目录 BloomFilter 原理: 问题引入:黑名单管理程序 哈希.哈希函数 BloomFilter : 3.4 BloomFilter 的缺陷.改进: 代码实现 黑名单blacklist.py: ...
- 基于RAG的MaxKB知识库问答系统如何选择向量模型
在MaxKB中替换向量模型前,我们需要先了解向量相关的原理和技术,此处不做赘述,大家可以自行学习.可以了解下Embedding.Embedding核心,向量库等内容. 一.MaxKB 默认向量模型 M ...
- LCP 11. 期望个数统计
地址:https://leetcode-cn.com/problems/qi-wang-ge-shu-tong-ji/ <?php /** 某互联网公司一年一度的春招开始了,一共有 n 名面试者 ...
- 基于pandas的数据清洗 -- 异常值的清洗
博客地址:https://www.cnblogs.com/zylyehuo/ 开发环境 anaconda 集成环境:集成好了数据分析和机器学习中所需要的全部环境 安装目录不可以有中文和特殊符号 jup ...