Condition
jdk1.5后,提供了Condition接口,主要常用的实现类是AQS里的ConditionObject;常用的方法await(),single()刚好对应Object类的wait(),notify();区别在于前者能指定唤醒阻塞的线程,看ArrayBlockedList源码可以看到,其阻塞的实现就是利用Condition实现的。下面开始研究下源码的实现。
首先看常见的用法
上面代码模拟了两个线程的同步的过程,首先condtion.await()和single()必须是在加锁范围内执行的,通过上面的执行步骤,可以清晰的理解线程之间是如何阻塞和唤醒的。
下面就按上述的场景流程,看下await()和single()过程中做了什么。
之前还得先了解下ConditonObject的结构,Node就是AQS里的节点,可以看到它自己有一个队列,和AQS的线程队列不是同一个。
1.thread1.lock()
thread1获取锁
2.thread2.lock()
thread2获取锁失败,进入线程队列并阻塞,最后AQS的线程队列为
3.conditon1.await()
3.1 addConditionWaiter
新建了一个Node,(Node.CONDITION=-2),firstWaiter和lasterWaiter都指向它,注意这里的队列和之前的线程队列不是同一个队列。
3.2fullyRelease
3.3 release
调用release方法,thread1释放锁
3.4 unparkSuccessor
最后将thread2阻塞唤醒
3.6 isOnSyncQueue
返回false,下一步park理解为阻塞在当前位置,唤醒后也从这里继续往下执行。
这次thread2被唤醒继续执行,thread1被阻塞。此时AQS线程队列
4.thread2.lock()上一步唤醒阻塞,这里继续往下执行,thread2获取到锁
5.condition1.single()
5.1 isHeldExclusively()
是否占有排它锁,返回ture
5.2 doSignal
firstWaiter和lastWaiter都为null
5.3 transferForSignal
最后唤醒thread1,等thread2执行完unlock()释放锁后,thread1继续执行。
大体通过代码自己分析了一遍过程,里面还有很多细节需要深究
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
2020-08-03 PostgreSQL 常用函数