前言
相关系列
- 《Java & Lock & 目录》(持续更新)
- 《Java & Lock & Condition & 源码》(学习过程/多有漏误/仅作参考/不再更新)
- 《Java & Lock & Condition & 总结》(学习总结/最新最准/持续更新)
- 《Java & Lock & Condition & 问题》(学习解答/持续更新)
涉及内容
- 《Java & Lock & 总结》
- 《Java & Lock & AQS & 总结》
- 《Java & Lock & ReentrantLock & 总结》
概述
简介
Condition @ 条件接口被设计用于定义条件机制。条件机制的本质是线程管理机制,用于在并发环境下对线程进行有序协调/精确控制,即令线程有序的等待/唤醒。对于条件机制我们可能并不陌生,原因是我们熟悉的ReentrantLock @ 可重入锁类及ReentrantReadWriteLock @ 可重入读写锁类中便存在条件机制,并且其还为这些具有独占特性的经典Lock @ 锁接口实现类提供了暂时解除独占的能力。这具体表现为我们可以通过锁接口定义的newCondition()方法获取条件接口对象,并通过该条件接口对象令已独占持有锁的线程暂时解除独占且管理至其重新恢复独占为止。而正因为我们通常会在可重入锁类/可重入读写锁类中比条件接口更早的接触到条件机制,并又在频繁使用的过程中对其“条件机制”的功能烂熟于心,从而导致许多开发者在无意间对条件机制的理解产生了错误,即直接将可重入锁类/可重入读写锁类这种提供暂时解除独占能力的条件机制视作条件机制本身,并进而将之与JVM层面synchronized关键字的wait/notify(等待/通知)机制进行对比,原因是等待/通知机制同样提供了暂时解除独占的能力。
为什么说这种理解是错误的呢?原因是仅提供令线程等待/唤醒基本功能定义的条件接口/条件机制是不含任何逻辑性/目的性的。线程具体会出于什么原因/条件/目的,又是以什么方式等待/唤醒这些都由条件接口的实现类具体决定。故而可重入锁类/可重入读写锁类这种提供暂时解除独占能力的条件机制本质上只是对条件机制定义的一种实现,并无法全权代表条件机制定义本身。因此真正可以与等待/通知机制进行对比的条件机制也仅限于可重入锁类/可重入读写锁类的条件机制实现,因为只要存在相应需求/意愿,开发者完全可以基于自身设计构造一套截然不同的条件机制实现。
条件接口只有ConditionObject @ 条件对象一个实现类。条件接口在Java JDK中有且仅有条件对象类一个实现类,该类以内部类的形式存在于AQS类中,并基于AQS类的作用/结构/逻辑构建出一套用于对暂时解除同步的AQS访问线程进行管理的条件机制实现,该知识点会在AQS类/条件对象类的相应文章中详述。条件对象类的条件机制实现非常重要,因为AQS类是经典锁接口实现类的通用底层实现,因此各个经典锁接口实现类的条件机制实际上都是基于AQS类的条件机制而实现的,或者更准确的说包含可重入锁类/可重入读写锁类在内的经典锁接口实现类的条件机制实现实际上都是AQS类的条件机制实现。
方法
等待
-
void await() throws InterruptedException —— 等待 —— 令当前线程在当前条件中进入等待状态。该方法是等待方法“阻塞”形式的实现,当前线程会无限等待至因为信号而唤醒为止。当前线程在进入方法/等待持有期间如果已/被中断会抛出中断异常,但中断状态会被清除。
-
void awaitUninterruptibly() —— 等待(不可中断) —— 令当前线程在当前条件中进入等待状态。该方法是等待方法“阻塞不可中断”形式的实现,当前线程会无限等待至因为信号而唤醒为止。当前线程在进入方法/等待持有期间如果已/被中断不会抛出中断异常,但中断状态会被保留。
-
boolean await(long time, TimeUnit unit) throws InterruptedException —— 等待 —— 令当前线程在当前条件中进入等待状态。该方法是等待方法“超时”形式的实现之一,当前线程会有限等待至因为信号而唤醒为止并返回true,超时指定等待时间则返回false。当前线程在进入方法/等待持有期间如果已/被中断会抛出中断异常,但中断状态会被清除。
-
long awaitNanos(long nanosTimeout) throws InterruptedException —— 等待纳秒 —— 令当前线程在当前条件中进入等待状态。该方法是等待方法“超时”形式的实现之一,当前线程会有限等待至因为信号而唤醒为止并返回剩余等待纳秒,超时指定等待时间则返回0或负数。当前线程在进入方法/等待持有期间如果已/被中断会抛出中断异常,但中断状态会被清除。
-
boolean awaitUntil(Date deadline) throws InterruptedException —— 等待单位 —— 令当前线程在当前条件中进入等待状态。该方法是等待方法“超时”形式的实现之一,当前线程会有限等待至因为信号而唤醒为止并返回true,超时指定等待时间则返回false。当前线程在进入方法/等待持有期间如果已/被中断会抛出中断异常,但中断状态会被清除。
信号
-
void signal() —— 信号 —— 唤醒一条在当前条件中等待的线程。
-
void signalAll() —— 信号全部 —— 唤醒所有在当前条件中等待的线程。