1.2 源码分析
AQS,Lock,Condition,ConditionObject
之间的关系:
以ReentrantLock为例, ConditionObject是AQS的内部类,实现了Condition接口,Lock中提供newCondition()方法,委托给内部AQS的实现Sync来创建ConditionObject对象,享受AQS对Condition的支持。
从上面的例子可以看出,条件队列的流程大概是这样 lock -> await -> signal -> unlock
waitStatus可以取五种状态:
- 初始化为0,啥也不表示,之后会被置signal。
- 1表示cancelled,取消当前线程对锁的争夺。
- -1表示signal,表示当前节点释放锁后需要唤醒后面可被唤醒的节点。
- -2表示condition,我们这篇的重点,表示当前节点在条件队列中。
- -3表示propagate,表示释放共享资源的时候会向后传播释放其他共享节点。
1.2.1 等待队列
等待队列是一个FIFO的队列,在队列中的每个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程,如果一个线程调用了Condition.await()方法,那么该线程将会释放锁、构造成节点加入等待队列并进入等待状态。
Condition拥有首尾节点的引用,而新增节点只需要将原有的尾节点nextWaiter指向它,并且更新尾节点即可。
同步队列和等待队列之间的关系
Condition的实现是同步器的内部类,因此每个Condition实例都能够访问同步器提供的方法,相当于每个Condition都拥有所属同步器的引用
1.2.2 等待
await代码
public final void await() throws InterruptedException {
// 1. 当前线程被中断,直接抛出异常
if (Thread.interrupted())
throw new InterruptedException();
// 2. 添加到条件队列中
Node node = addConditionWaiter();
// 3. 释放同步资源,锁
int savedState = fullyRelease(node);
int interruptMode = 0;
// 4. 如果这个节点的线程不在同步队列中,说明该线程还不具备竞争锁的资格
while (!isOnSyncQueue(node)) {
// 挂起线程
LockSupport.park(this);
// 线程中断退出
if ((interruptMode = checkInterruptWhileWaiting(node)) != 0)
break;
}
// 退出循环,被唤醒之后,进入阻塞队列,等待获取锁 acquireQueued
if (acquireQueued(node, savedState) && interruptMode != THROW_IE)
interruptMode = REINTERRUPT;
if (node.nextWaiter != null) // clean up if cancelled
unlinkCancelledWaiters();
if (interruptMode != 0)
reportInterruptAfterWait(interruptMode);
}
复制代码
Node addConditionWaiter() 添加到条件队列
private Node addConditionWaiter() {
Node t = lastWaiter;
// If lastWaiter is cancelled, clean out.
if (t != null && t.waitStatus != Node.CONDITION) {
// 遍历整个条件队列,将已取消的所有节点清除出列
unlinkCancelledWaiters();
// t 重新赋值
t = lastWaiter;
}
Node node = new Node(Thread.currentThread(), Node.CONDITION);
// t == null 表示队列此时为空,初始化firstWaiter
if (t == null)
firstWaiter = node;
else
t.nextWaiter = node;
// 将尾指针指向新建的node
lastWaiter = node;
return node;
}
复制代码
上面其实也就是一个单链表的操作. void unlinkCancelledWaiters() 清除队列中已经取消等待的节点
private void unlinkCancelledWaiters() {
Node t = firstWaiter;
// trail这里表示取消节点的前驱节点
Node trail = null;
while (t != null) {
Node next = t.nextWaiter;
if (t.waitStatus != Node.CONDITION) {
t.nextWaiter = null;
if (trail == null)
firstWaiter = next;
else
trail.nextWaiter = next;
if (next == null)
lastWaiter = trail;
}
else
trail = t;
t = next;
}
}
复制代码
1.2.3.通知
调用Condition的signal()方法,将会唤醒在等待队列中等待时间最长的节点(首节点),在 唤醒节点之前,会将节点移到同步队列中。
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Java开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上Java开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024b (备注Java)
最后
俗话说,好学者临池学书,不过网络时代,对于大多数的我们来说,我倒是觉得学习意识的觉醒很重要,这是开始学习的转折点,比如看到对自己方向发展有用的信息,先收藏一波是一波,比如如果你觉得我这篇文章ok,先点赞收藏一波。这样,等真的沉下心来学习,不至于被找资料分散了心神。慢慢来,先从点赞收藏做起,加油吧!
另外,给大家安排了一波学习面试资料:
以上就是本文的全部内容,希望对大家的面试有所帮助,祝大家早日升职加薪迎娶白富美走上人生巅峰!
习意识的觉醒很重要,这是开始学习的转折点,比如看到对自己方向发展有用的信息,先收藏一波是一波,比如如果你觉得我这篇文章ok,先点赞收藏一波。这样,等真的沉下心来学习,不至于被找资料分散了心神。慢慢来,先从点赞收藏做起,加油吧!
另外,给大家安排了一波学习面试资料:
[外链图片转存中…(img-g3imtSQg-1712088833080)]
[外链图片转存中…(img-R3qEaNmK-1712088833080)]
以上就是本文的全部内容,希望对大家的面试有所帮助,祝大家早日升职加薪迎娶白富美走上人生巅峰!