news 2026/5/12 10:10:03

深入浅出Java Condition 的await和signal机制(一)

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
深入浅出Java Condition 的await和signal机制(一)
每个对象都可以调用 Object 的 wait/notify 方法来实现等待/通知机制。而 Condition 接口也提供了类似的方法。
Condition 接口一共提供了以下 7 个方法:
  • await():线程等待直到被通知或者中断。类似于Object.wait()
  • awaitUninterruptibly():线程等待直到被通知,即使在等待时被中断也不会返回。没有与之对应的 Object 方法。
  • await(long time, TimeUnit unit):线程等待指定的时间,或被通知,或被中断。类似于Object.wait(long timeout),但提供了更灵活的时间单位。
  • awaitNanos(long nanosTimeout):线程等待指定的纳秒时间,或被通知,或被中断。没有与之对应的 Object 方法。
  • awaitUntil(Date deadline):线程等待直到指定的截止日期,或被通知,或被中断。没有与之对应的 Object 方法。
  • signal():唤醒一个等待的线程。类似于Object.notify()
  • signalAll():唤醒所有等待的线程。类似于Object.notifyAll()
以下是Object 类的主要方法,我们来做一下对比:
  • wait():线程等待直到被通知或者中断。
  • wait(long timeout):线程等待指定的时间,或被通知,或被中断。
  • wait(long timeout, int nanos):线程等待指定的时间,或被通知,或被中断。
  • notify():唤醒一个等待的线程。
  • notifyAll():唤醒所有等待的线程。

Condition 源码分析

要想深入理解 Condition 的实现原理,就需要挖掘一下 Condiiton 的源码。
创建一个 Condition 对象可以通过lock.newCondition()来创建,这个方法实际上会 new 一个ConditionObject的对象,ConditionObject 是 AQS 的一个内部类,我们就拿 ReentrantLock 来举例说明吧。
public class ReentrantLock implements Lock, java.io.Serializable { abstract static class Sync extends AbstractQueuedSynchronizer { final ConditionObject newCondition() { return new ConditionObject(); } } public Condition newCondition() { return sync.newCondition(); } }
AQS 内部维护了一个先进先出(FIFO)的双端队列,并使用了两个引用 head 和 tail 用于标识队列的头部和尾部。
Condition 内部也使用了同样的方式,内部维护了一个先进先出(FIFO)的单向队列,我们把它称为等待队列。
所有调用 await 方法的线程都会加入到等待队列中,并且线程状态均为等待状态。firstWaiter 指向首节点,lastWaiter 指向尾节点,源码如下:
public class ConditionObject implements Condition, java.io.Serializable { private static final long serialVersionUID = 1173984872572414699L; /** First node of condition queue. */ private transient Node firstWaiter; /** Last node of condition queue. */ private transient Node lastWaiter; }
Node 中的 nextWaiter 指向队列中的下一个节点。并且进入到等待队列的 Node 节点状态都会被设置为 CONDITION。
同时还有一点需要注意:我们可以多次调用newCondition()方法创建多个 Condition 对象,也就是一个 lock 可以持有多个等待队列。
而如果是 Object 方式的话,就只能有一个同步队列和一个等待队列。
因此,ReentrantLock 等 AQS 是可以持有一个同步队列和多个等待队列的,new 多个 Condition 就行了。示意图如下:
AQS持有多个Condition
持有多个等待队列的好处是什么呢?我们可以通过下面这个例子来说明:
public class BoundedBuffer<T> { private final LinkedList<T> buffer; // 使用 LinkedList 作为缓冲区 private final int capacity; // 缓冲区最大容量 private final ReentrantLock lock; // 互斥锁 private final Condition notEmpty; // 缓冲区非空条件 private final Condition notFull; // 缓冲区非满条件 public BoundedBuffer(int capacity) { this.capacity = capacity; this.buffer = new LinkedList<>(); this.lock = new ReentrantLock(); this.notEmpty = lock.newCondition(); this.notFull = lock.newCondition(); } // 放入一个元素 public void put(T item) throws InterruptedException { lock.lock(); try { // 如果缓冲区满,等待 while (buffer.size() == capacity) { notFull.await(); } buffer.add(item); // 通知可能正在等待的消费者 notEmpty.signal(); } finally { lock.unlock(); } } // 取出一个元素 public T take() throws InterruptedException { lock.lock(); try { // 如果缓冲区空,等待 while (buffer.isEmpty()) { notEmpty.await(); } T item = buffer.removeFirst(); // 通知可能正在等待的生产者 notFull.signal(); return item; } finally { lock.unlock(); } } }
考虑这个简单的有界缓冲区 BoundedBuffer,其中生产者放入元素,消费者取出元素。我们将使用两个 Condition:一个表示缓冲区不为空(用于消费者等待),另一个表示缓冲区不满(用于生产者等待)。
生产者调用 put 方法放入元素,如果缓冲区已满,则等待 notFull 条件。消费者调用 take 方法取出元素,如果缓冲区为空,则等待 notEmpty 条件。当一个元素被放入或取出时,相应的条件会发出信号,唤醒等待的线程。
使用多个 Condition 对象的主要优点是为锁提供了更细粒度的控制,可以实现更复杂的同步场景,比如上面提到的有界缓冲区。
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/5/10 14:38:14

开发外卖取餐码语音播报工具,输入取餐码自动语音提醒,支持自定义播报语速,解决外卖多找码难,手忙脚乱问题,适配手机端,无需复杂操作,精准播报不报错。

1. 实际应用场景与痛点 场景 现代人点外卖频率很高&#xff0c;尤其是上班族、学生、家庭用户。外卖到达后&#xff0c;骑手会在门口打电话或发短信告知取餐码&#xff0c;但经常出现&#xff1a; - 手里提着东西&#xff0c;不方便看手机 - 环境嘈杂听不清骑手说的取餐码 - …

作者头像 李华
网站建设 2026/5/9 11:34:53

携手NVIDIA,英飞凌为人形机器人提供精准运动与高效解决方案

电机驱动芯片 全球功率系统和物联网领域的半导体领导者英飞凌科技股份公司&#xff08;FSE代码&#xff1a;IFX/OTCQX代码&#xff1a;IFNNY&#xff09;宣布携手NVIDIATechnology&#xff08;简称&#xff1a;NVIDIA英伟达&#xff0c;下同&#xff09;加速人形机器人领域的研…

作者头像 李华
网站建设 2026/5/10 14:46:42

亲测好用 10个一键生成论文工具:自考毕业论文+开题报告高效写作测评

在当前学术写作日益依赖智能化工具的背景下&#xff0c;自考学生在撰写毕业论文和开题报告时也面临着选题困难、资料查找繁琐、格式规范不熟悉等普遍问题。为了帮助广大自考生更高效地完成论文写作任务&#xff0c;我们基于2026年的实测数据与真实用户反馈&#xff0c;对市面上…

作者头像 李华
网站建设 2026/5/9 19:14:50

SEW变频器MC07A300-503-4-10 08273049

SEW变频器MC07A300-503-4-10 08273049 详细介绍 一、产品概述 SEW变频器MC07A300-503-4-10&#xff08;序列号&#xff1a;08273049&#xff09;是德国SEW-EURODRIVE公司推出的工业级模块化变频器&#xff0c;专为三相异步电机设计&#xff0c;属于MOVIMOT系列中的紧凑型产品…

作者头像 李华
网站建设 2026/5/10 1:18:24

SEW变频器MCV40A0750-503-4-0T 08274851

SEW变频器MCV40A0750-503-4-0T 08274851 技术详解一、产品定位与系列概述SEW-Eurodrive的MCV系列变频器专为工业自动化场景设计&#xff0c;MCV40A0750-503-4-0T属于模块化紧凑型变频器家族。该型号采用三相380-480V交流供电&#xff0c;适配0.75kW三相异步电机&#xff08;型号…

作者头像 李华
网站建设 2026/5/11 6:50:45

SEW变频器MCV40A0300-203-4-00 08272719

孙13665068812第一章&#xff1a;产品概述 SEW MCV40A系列变频器是工业自动化领域的核心驱动设备&#xff0c;型号MCV40A0300-203-4-00专为三相异步电动机设计。其核心参数解析&#xff1a; 功率等级&#xff1a;0300表示额定功率3.0 kW&#xff08;对应400V级&#xff09;电…

作者头像 李华