1、Condition与Lock的关系
Condition本身也是一个接口,其功能和wait/notify类似,如下所示:
public interface Condition {
void await() throws InterruptedException;
boolean await(long time, TimeUnit unit) throws InterruptedException;
long awaitNanos(long nanosTimeout) throws InterruptedException;
void awaitUninterruptibly();
boolean awaitUntil(Date deadline) throws InterruptedException;
void signal();
void signalAll();
}
wait()/notify()必须和synchronized一起使用,Condition也必须和Lock一起使用。因此,在Lock的
接口中,有一个与Condition相关的接口:
public interface Lock {
void lock();
void lockInterruptibly() throws InterruptedException;
// 所有的Condition都是从Lock中构造出来的
Condition newCondition();
boolean tryLock();
boolean tryLock(long time, TimeUnit unit) throws InterruptedException;
void unlock();
}
2、Condition的使用场景
以ArrayBlockingQueue为例。如下所示为一个用数组实现的阻塞队列,执行put(…)操作的时候,队
列满了,生产者线程被阻塞;执行take()操作的时候,队列为空,消费者线程被阻塞。
3、Condition实现原理
可以发现,Condition的使用很方便,避免了wait/notify的生产者通知生产者、消费者通知消费者的问题。具体实现如下:
由于Condition必须和Lock一起使用,所以Condition的实现也是Lock的一部分。首先查看互斥锁和读写锁中Condition的构造方法
首先,读写锁中的 ReadLock 是不支持 Condition 的,读写锁的写锁和互斥锁都支持Condition。虽然它们各自调用的是自己的内部类Sync,但内部类Sync都继承自AQS。因此,上面的代码sync.newCondition最终都调用了AQS中的newCondition:
每一个Condition对象上面,都阻塞了多个线程。因此,在ConditionObject内部也有一个双向链表组成的队列,如下所示: