1.Condition的使用
Condition接口可作为 wait/notify 的替代品来实现等待/通知,它为解决过早唤醒问题提供了支持,并解决了 Object.wait(long)不能区分其返回是否是由等待超时而导致的问题。Condition 接口定义的 await 方法、 signal 方法和 signalAII 方法分别相当于 Object.wait() 、Object.notify() 和 Object.notify All() 。
Lock.newCondition() 的返回值就是一个 Condition 实例,因此调用任意一个显式锁实例的 newCondition 方法可以创建一个相应的 Condition 接口。使用模板:
class ConditionUsage {
private final Lock lock = new Reentranlock();
private final Condition condition = lock.newCondition();
public void aGuaredMethod() throws InterruptedException {
lock.lock();
try {
while(保护条件不成立){
condition.await() ;
}
//执行目标动作
doAction();
} finally {
lock.unlock();
}
}
public void anNotificationMethod() throws InterruptedException {
lock.lock();
try {
//更新共享变量
changeState();
condition.signal();
}finally {
lock.unlock();
}
}
}
2.解决过早唤醒问题
Condition接口本身只是对解决过早唤醒问题提供了支持。要真正解决过早唤醒问题,我们需要通过应用代码维护保护条件与条件变量之间的对应关系,即使用不同的保护条件的等待线程需要调用不同的条件变量的 await 方法来实现其等待,并使通知线程在更新了相关共享变量之后,仅调用与这些共享变量有关的保护条件所对应的条件变量的signal/signalAII 方法来实现通知。
3.Condition.awaitUntil(Date deadline)
Condition.awaitUntil(Date deadline)可以用于实现带超时时间限制的等待,并且该方法的返回值能够区分该方法调用是由于等待超时而返回还是由于其他线程执行了相应条件变量的 signal/signalAll 方法而返回。Condition.awaitUntil(Date)返回值 true 表示进行的等待尚未达到最后期限。即此时方法的返回是由于其他线程执行了相应条件变量的 signal/signalAll 方法。在等待线程被唤醒到其再次申请相应的显式锁的这段时间内,其他线程(或者通知线程本身)可能已经抢先获得相应的显式锁并在其临界区中更新了相关共享变量而使得等待线程所需的保护条件重新不成立。因此,Condition.awaitUntil(Date)返回 true (等待未超时)的情况下我们可以选择继续等待。