凡事都在事上磨,这样才能精进,成长进步提高! ------ 博客园首页

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继续执行。

 

大体通过代码自己分析了一遍过程,里面还有很多细节需要深究

posted @   追风fc  阅读(25)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
历史上的今天:
2020-08-03 PostgreSQL 常用函数
点击右上角即可分享
微信分享提示