Condition

发布时间 2023-08-03 10:29:19作者: 追风fc

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

 

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