youyichannel

志于道,据于德,依于仁,游于艺!

0%

Lock全解读05

Condition 原理

ConditionObject是同步器AQS的累不累,因为Condition的操作需要获取相关联的锁,所以作为同步器的内部类也较为合理。每个Condition对象都包含一个队列(等待队列),该队列是Condition对象实现等待/通知功能的关键。

等待队列是一个FIFO的队列,在队列中的每个节点都包含一个线程应用,该线程就是在Condition对象上等待的线程,如果一个线程调用了Condition.await()方法,那么该线程将会释放锁、构造成节点加入等待队列并进入等待状态。事实上,节点的定义复用了同步器中节点的定义,也就是,同步队列和等待队列中节点类型都是同步器的静态内部类Node,共享NodeStatus。

一个Condition包含一个等待队列,Condition拥有首节点(firstWaiter)和尾节点(lastWaiter)。当前线程调用Condition.await()方法,将会以当前线程构造节点,并将节点从尾部加入等待队列,等待队列的基本结构:

如图所示,Condition拥有首尾节点的应用,而新增节点只需要将原有的尾节点nextWaiter指向它,并且更新尾节点即可。上述节点应用更新的过程并没有使用CAS保证,原因在于调用await()方法的线程当前是持有锁的,也就是说该过程是由锁来保证线程安全的。

在Object的监视器模型上,一个对象拥有一个同步队列和等待队列,而并发包中的Lock(或者说同步器AQS)拥有一个同步队列和多个等待队列,其对应关系:

过程描述:一个线程持有锁,调用了await()方法之后加入了等待队列进行排队,当这个线程被唤醒(需要执行await之后的代码),需要重新竞争锁。如果竞争锁失败,就会加入到同步队列中进行排队。如果排到了同步队列的头部并且争抢锁成功,就继续执行await之后的代码。如果在执行过程中又调用了await()方法,就再次回到等待队列中,以此循环下去。