前面的文章中,我们了解了Java中的
Lock接口,以及相关的实现类ReentrantLock、ReentrantReadWriteLock。它们都是通过聚合一个AQS来实现的。同时讨论了为什么有了Synchronized关键字之后还要有Lock。我们知道
Synchronized关键字是Monitor机制在Java中的一种具体实现,每个对象都有wait()、notify()和notifyAll()方法来进行线程通信。那么问题来了,在提出了
Lock之后,我们使用Lock加锁的时候有没有类似的一组监视器方法呢?这就是我们今天要讨论的Condition接口。Condition接口和Object类的监视器方法有相同又有不同。
定义
先来看下Condition接口里定义的方法:

是不是和Object中定义的方法很类似。
使用
ConditionObject类实现了Condition接口,作为一个AQS的内部类,所以它的创建依靠于Lock对象,通过newCondition()方法创建它。
使用也十分简单,但是记得使用时要加锁。
1 | Lock lock = new ReentrantLock() ; |
阻塞队列就是使用
Condition来实现生产者和消费者的通信的
实现
Condition作为AQS的内部类被实现,所以它是可以共享一些AQS的资源的。
Condition的实现有三个关键点:等待队列、等待和通知。
同步队列和等待队列
同步队列:线程获取同步状态失败时会进入的队列,首节点表示获取同步状态成功的节点。
等待队列:存放调用了Condition.await()方法的线程节点。
await()
当线程执行Condition.await()时,线程节点从同步队列中被移除,加入对应Condition的等待队列中。
signal()
当线程执行Condition.signal()时,对应Condition等待队列中的首节点被移除,转而加入的同步队列中。
需要注意的是,对于同一个
Lock,等待队列是可以有多个的。同时可以发现,对于一个线程节点,要么在同步队列中,要么在等待队列中。