0

0

Java并发编程中的Condition与等待通知机制

P粉602998670

P粉602998670

发布时间:2026-01-14 15:51:16

|

951人浏览过

|

来源于php中文网

原创

condition是java.util.concurrent.locks中需配合reentrantlock使用的多条件等待工具,区别于object的wait/notify在于:一个锁可绑定多个condition实现语义分离,而synchronized仅有一个隐式队列;await/signal必须在lock后unlock前调用,且需用while防虚假唤醒。

java并发编程中的condition与等待通知机制

Condition 是什么,和 Object 的 wait/notify 有什么区别

Condition 是 java.util.concurrent.locks 包中用于替代 Object.wait() / Object.notify() 的协作工具,必须配合 ReentrantLock 使用。它不是独立存在的,也不能在 synchronized 块里用 —— 这是第一个容易踩的坑。

核心区别在于:一个 ReentrantLock 可以绑定多个 Condition 实例,而 synchronized 块里的每个对象只有一个隐式等待队列。这意味着你可以按业务语义拆分等待逻辑,比如生产者用 notFull、消费者用 notEmpty,互不干扰。

  • wait()/notify() 必须在 synchronized 方法或块中调用,否则抛 IllegalMonitorStateException
  • Condition.await()/signal() 必须在 lock.lock() 之后、lock.unlock() 之前调用,否则抛 IllegalMonitorStateException
  • notifyAll() 是“唤醒全部”,但无法指定唤醒哪类线程;Condition.signalAll() 只唤醒该 Condition 上等待的线程,更精准

如何正确创建和使用 Condition 实例

不能直接 new Condition,必须通过 Lock.newCondition() 获取。常见错误是把同一个 Condition 实例混用于不同条件判断,或者在未持有锁时调用 await()

典型写法是为每种等待场景定义独立的 Condition 变量:

立即学习Java免费学习笔记(深入)”;

BeatBot
BeatBot

Splash的AI音乐生成器,AI歌曲制作人!

下载
private final ReentrantLock lock = new ReentrantLock();
private final Condition notEmpty = lock.newCondition();
private final Condition notFull = lock.newCondition();

// 消费者等待非空
public void take() throws InterruptedException {
    lock.lock();
    try {
        while (queue.isEmpty()) {
            notEmpty.await(); // 释放锁并进入等待
        }
        // ...取元素
        notFull.signal(); // 通知生产者可以继续放了
    } finally {
        lock.unlock();
    }
}
  • 一定要用 while 判断条件,而不是 if —— 防止虚假唤醒(spurious wakeup)
  • await() 会自动释放锁,被唤醒后需重新竞争锁;signal() 不释放锁,只唤醒一个线程
  • 如果想唤醒所有等待该条件的线程,用 signalAll(),比如广播中断或重置状态时

await() 被中断时会发生什么

Condition.await() 是响应中断的:如果线程在等待中被 interrupt(),会立即抛出 InterruptedException 并清除中断状态。这点和 Object.wait() 一致,但比 LockSupport.park() 更明确。

关键点在于:异常抛出后,当前线程**不会自动重新获取锁**,而是直接退出 try 块,由 finally 中的 unlock() 保证锁释放。所以你不需要、也不应该在 catch 块里手动 unlock。

  • 不要吞掉 InterruptedException,除非你明确要忽略中断(极少见)
  • 若需恢复中断状态,可在 catch 块末尾调用 Thread.currentThread().interrupt()
  • awaitUninterruptibly() 是不响应中断的版本,但用得少,因为会丢失协作控制能力

Condition 在线程池或异步任务中能不能用

能用,但要格外小心生命周期。Condition 本身没有线程绑定,但它依赖的 ReentrantLock 和共享状态(比如队列、计数器)必须是线程安全且长期有效的。

常见陷阱是:在线程池中启动一个任务去 await,但该任务被取消或超时后,对应的 Condition 等待线程可能滞留,甚至因未 signal 导致其他线程永久阻塞。

  • 避免在 CompletableFuture@Async 方法里直接 await,除非你能确保 signal 一定发生
  • 考虑用 awaitNanos(long)awaitUntil(Date) 带超时的版本,防止无限等待
  • 如果底层是 Netty 或 Vert.x 这类事件驱动框架,优先用它们自己的通知机制(如 Promise / Handler),而非 Condition

Condition 的价值在于精细控制多条件等待,但它要求你对锁的持有、唤醒时机和线程状态有清晰把握 —— 少一个 while、漏一次 signal、错一次 lock/unlock 配对,就可能卡死或数据错乱。

相关文章

编程速学教程(入门课程)
编程速学教程(入门课程)

编程怎么学习?编程怎么入门?编程在哪学?编程怎么学才快?不用担心,这里为大家提供了编程速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
if什么意思
if什么意思

if的意思是“如果”的条件。它是一个用于引导条件语句的关键词,用于根据特定条件的真假情况来执行不同的代码块。本专题提供if什么意思的相关文章,供大家免费阅读。

844

2023.08.22

while的用法
while的用法

while的用法是“while 条件: 代码块”,条件是一个表达式,当条件为真时,执行代码块,然后再次判断条件是否为真,如果为真则继续执行代码块,直到条件为假为止。本专题为大家提供while相关的文章、下载、课程内容,供大家免费下载体验。

104

2023.09.25

线程和进程的区别
线程和进程的区别

线程和进程的区别:线程是进程的一部分,用于实现并发和并行操作,而线程共享进程的资源,通信更方便快捷,切换开销较小。本专题为大家提供线程和进程区别相关的各种文章、以及下载和课程。

743

2023.08.10

Java 并发编程高级实践
Java 并发编程高级实践

本专题深入讲解 Java 在高并发开发中的核心技术,涵盖线程模型、Thread 与 Runnable、Lock 与 synchronized、原子类、并发容器、线程池(Executor 框架)、阻塞队列、并发工具类(CountDownLatch、Semaphore)、以及高并发系统设计中的关键策略。通过实战案例帮助学习者全面掌握构建高性能并发应用的工程能力。

97

2025.12.01

promise的用法
promise的用法

“promise” 是一种用于处理异步操作的编程概念,它可以用来表示一个异步操作的最终结果。Promise 对象有三种状态:pending(进行中)、fulfilled(已成功)和 rejected(已失败)。Promise的用法主要包括构造函数、实例方法(then、catch、finally)和状态转换。

334

2023.10.12

html文本框类型介绍
html文本框类型介绍

html文本框类型有单行文本框、密码文本框、数字文本框、日期文本框、时间文本框、文件上传文本框、多行文本框等等。详细介绍:1、单行文本框是最常见的文本框类型,用于接受单行文本输入,用户可以在文本框中输入任意文本,例如用户名、密码、电子邮件地址等;2、密码文本框用于接受密码输入,用户在输入密码时,文本框中的内容会被隐藏,以保护用户的隐私;3、数字文本框等等。

425

2023.10.12

JavaScript浏览器渲染机制与前端性能优化实践
JavaScript浏览器渲染机制与前端性能优化实践

本专题围绕 JavaScript 在浏览器中的执行与渲染机制展开,系统讲解 DOM 构建、CSSOM 解析、重排与重绘原理,以及关键渲染路径优化方法。内容涵盖事件循环机制、异步任务调度、资源加载优化、代码拆分与懒加载等性能优化策略。通过真实前端项目案例,帮助开发者理解浏览器底层工作原理,并掌握提升网页加载速度与交互体验的实用技巧。

3

2026.03.06

Rust内存安全机制与所有权模型深度实践
Rust内存安全机制与所有权模型深度实践

本专题围绕 Rust 语言核心特性展开,深入讲解所有权机制、借用规则、生命周期管理以及智能指针等关键概念。通过系统级开发案例,分析内存安全保障原理与零成本抽象优势,并结合并发场景讲解 Send 与 Sync 特性实现机制。帮助开发者真正理解 Rust 的设计哲学,掌握在高性能与安全性并重场景中的工程实践能力。

21

2026.03.05

PHP高性能API设计与Laravel服务架构实践
PHP高性能API设计与Laravel服务架构实践

本专题围绕 PHP 在现代 Web 后端开发中的高性能实践展开,重点讲解基于 Laravel 框架构建可扩展 API 服务的核心方法。内容涵盖路由与中间件机制、服务容器与依赖注入、接口版本管理、缓存策略设计以及队列异步处理方案。同时结合高并发场景,深入分析性能瓶颈定位与优化思路,帮助开发者构建稳定、高效、易维护的 PHP 后端服务体系。

108

2026.03.04

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 4.2万人学习

C# 教程
C# 教程

共94课时 | 10.8万人学习

Java 教程
Java 教程

共578课时 | 78.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号