Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

前面的文章中,我们了解了Java中的Lock接口,以及相关的实现类ReentrantLockReentrantReadWriteLock。它们都是通过聚合一个AQS来实现的。同时讨论了为什么有了Synchronized关键字之后还要有Lock

我们知道Synchronized关键字是Monitor机制在Java中的一种具体实现,每个对象都有wait()notify()notifyAll()方法来进行线程通信。

那么问题来了,在提出了Lock之后,我们使用Lock加锁的时候有没有类似的一组监视器方法呢?这就是我们今天要讨论的Condition接口。Condition接口和Object类的监视器方法有相同又有不同。

定义

先来看下Condition接口里定义的方法:

M1DemT.png

是不是和Object中定义的方法很类似。

使用

ConditionObject类实现了Condition接口,作为一个AQS的内部类,所以它的创建依靠于Lock对象,通过newCondition()方法创建它。

使用也十分简单,但是记得使用时要加锁。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
Lock lock = new ReentrantLock() ;
Condition condition = lock.newCondition();

//线程A
lock.lock();
try {
condition.await();
} catch (InterruptedException e) {
e.printStackTrace();
}finally {
lock.unlock();
}

//线程B
lock.lock();
try{
condition.signal();
}catch(InterruptedException e){
e.printStackTrace();
}finally{
lock.unlock();
}

阻塞队列就是使用Condition来实现生产者和消费者的通信的

实现

Condition作为AQS的内部类被实现,所以它是可以共享一些AQS的资源的。

Condition的实现有三个关键点:等待队列、等待和通知。

同步队列和等待队列

同步队列:线程获取同步状态失败时会进入的队列,首节点表示获取同步状态成功的节点。

等待队列:存放调用了Condition.await()方法的线程节点。

await()

当线程执行Condition.await()时,线程节点从同步队列中被移除,加入对应Condition的等待队列中。

signal()

当线程执行Condition.signal()时,对应Condition等待队列中的首节点被移除,转而加入的同步队列中。

需要注意的是,对于同一个Lock,等待队列是可以有多个的。

同时可以发现,对于一个线程节点,要么在同步队列中,要么在等待队列中。

评论