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,重新设置线程的中断状态。
-
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 从HTTP原因短语缺失研究HTTP/2和HTTP/3的设计差异
· 三行代码完成国际化适配,妙~啊~