一、Condition简介
任意一个Java对象,都拥有一组监视器方法(定义在Object类中),主要包括wait,notify,notifyAll方法,这些方法与synchornized关键字相配合,可以实现等待/通知模式。
Condition接口也提供了类似的Object的监视器方法,与Lock配合可以实现等待/通知模式。但是这两者在使用方式以及功能上还是有差别的。
Condition定义了等待/通知两种类型的方法,当前线程调用这些方法时,需要提前获取到Condition对象关联的锁。Condition对象是由Lock对象创建出来的,换句话说,Condition是依赖Lock对象的。
Condition在调用方法之前必须获取锁。使用方式如下图
Condition调用await方法后,当前线程会释放锁并在此等待,而其他线程调用Condition对象的singal方法,通知当前线程,当前线程才从await方法返回,并且在返回前已经获取了锁。
Contiditon定义的部分方法如下
二、Condition的实现分析
Condition的实现,主要包括等待队列,等待和通知。
1、等待队列
等待队列是一个FIFO的队列,在队列中的每个节点都包含了一个线程引用,该线程就是在Condition对象上等待的线程,
如果一个线程调用了Condition.await方法,那么该线程将会释放锁,构造成节点并加入等待队列进入等待状态。
一个Condition包含一个等待队列,Condition对象拥有首节点和尾节点的引用。当前线程调用await方法,将会构造节点并加入到等待队列尾部。等待队列的基本结构如图所示。
如图所示,Condition拥有首节点和尾节点的引用,而新增节点只需要将原有的尾节点的nextWaiter指向它,并且更新尾节点即可。上述节点引用更新的过程并没有使用CAS保证,因为调用await的线程必定是获取了锁的线程,也就是说,这个过程是由锁来保证线程安全的。
在Object的监视器模型上,一个对象拥有一个同步队列和一个等待队列,而并发包中的Lock拥有一个同步队列和多个等待队列,其关系图如图所示。