关于Monitor
A synchronization abstraction supporting waiting on arbitrary boolean conditions
Monitor类是作为ReentrantLock的一个替代,代码中使用 Monitor比使用ReentrantLock更不易出错,可读性也更强,并且也没有显著的性能损失,使用Monitor甚至有潜在的性能得到优化。下面我们整体上对Monitor的源码结构做一下梳理,总的来说也就在从jdk最原生的wait、notify.再做了一层warp。提供更加丰富的API。比如,当我们要实现一个blockingQueue的时候,原生的代码大概是这样写的
public class SafeBox<V> {
private V value;
public synchronized V get() throws InterruptedException {
while (value == null) {
wait();//vaule 为空 等待
}
//获得cpu,取出value
V result = value;
value = null;
notifyAll();//唤醒其他wait方法
return result;
}
public synchronized void set(V newValue) throws InterruptedException {
while (value != null) {
wait();//等待
}
//被唤醒后,给value赋值
value = newValue;
//唤醒
notifyAll();
}
}
上面的代码可能还不足以说明原生jdk中纯在的问题,但是原生的wait、notify无法做到更加精细的唤醒操作,而Condition它更强大的地方在于:能够更加精细的控制多线程的休眠与唤醒。对于同一个锁,我们可以创建多个Condition,就是多个监视器的意思。在不同的情况下使用不同的Condition。
例如,假如多线程读/写同一个缓冲区:当向缓冲区中写入数据之后,唤醒”读线程”;当从缓冲区读出数据之后,唤醒”写线程”
如果采用Object类中的wait(), notify(), notifyAll()实现该缓冲区,当向缓冲区写入数据之后需要唤醒”读线程”时,不可能通过notify()或notifyAll()明确的指定唤醒”读线程”,而只能通过notifyAll唤醒所有线程(但是notifyAll无法区分唤醒的线程是读线程,还是写线程)。当所有的线程都被唤醒,这里会再次产生一个锁的竞争. 但是,通过Condition,就能明确的指定唤醒读线程。我们在编程的时候可以指定唤醒任何一个线程,如下
public class SafeBox<V> {
private final ReentrantLock lock = new ReentrantLock();
private final Condition valuePresent = lock.newCondition();//read condition
private final Condition valueAbsent = lock.newCondition();//write condition
private V value;
public V get() throws InterruptedException {
lock.lock();
try {
while (value == null) {
//读线程等待
valuePresent.await();
}
V result = value;
value