0

0

详解Wait/Notify范式_在while循环中进行条件检查的必要性

P粉602998670

P粉602998670

发布时间:2026-02-12 14:46:44

|

194人浏览过

|

来源于php中文网

原创

wait()必须放在while循环里,因为可能遭遇虚假唤醒或条件被其他线程修改,if判断一次无法确保条件成立,易导致逻辑错误或数据不一致。

详解wait/notify范式_在while循环中进行条件检查的必要性

为什么 wait() 必须放在 while 循环里,不能用 if

因为 wait() 可能被虚假唤醒(spurious wakeup),也可能在重新获得锁后发现条件早已被其他线程改回不满足状态。用 if 判断一次就直接往下走,大概率导致逻辑错误或数据不一致。

典型现象:线程从 wait() 返回后,发现队列已空、缓冲区仍满、信号量没真正就绪,却继续执行消费/写入操作,触发 IndexOutOfBoundsException 或死锁。

  • 所有基于 wait()/notify() 的条件等待,都必须用 while 重检条件表达式
  • 条件变量(如 isEmptyisFull)必须是对象级别的共享状态,不能是局部计算值
  • 检查和 wait 必须在同一个 synchronized 块内,否则存在竞态窗口

标准写法长什么样:以生产者-消费者为例

核心不是“怎么写漂亮”,而是“怎么避免漏掉关键环节”。下面这段是经过验证的最小可靠模式:

synchronized (lock) {
    while (!conditionMet()) {
        lock.wait();
    }
    // 此时 conditionMet() 一定为 true,且持有锁
    doSomething();
}

注意三点:

  • conditionMet() 必须是可反复求值的布尔表达式,比如 queue.size() > 0,而不是缓存的临时变量 wasNotEmpty
  • wait() 前不能有 return、break 或其他提前退出逻辑,否则条件检查被跳过
  • 如果用了带超时的 wait(long timeout),返回后仍要再 check 条件——超时和唤醒都会跳出 wait

notify() 和 notifyAll() 选哪个?

绝大多数情况下该用 notifyAll(),而不是 notify()。这不是性能洁癖,而是避免条件竞争下的永久阻塞。

传声港
传声港

AI驱动的综合媒体服务平台,提供 “媒体发稿 + 自媒体宣发 + 效果监测” 一站式服务

下载

常见误判场景:多个等待线程监听不同条件(比如“非空”和“非满”),只调 notify() 可能唤醒错的人,而被唤醒者因条件不满足再次 wait,其他真正该醒的线程却永远卡住。

  • notify() 仅适用于:等待线程完全同质、条件完全一致、且唤醒任意一个都等价(极少见)
  • notifyAll() 开销并不比 notify() 高太多,JVM 会跳过无等待的线程
  • 别指望靠“精准唤醒”优化性能——条件复杂时,唤醒后仍要循环检查,本质仍是协作式调度

现代替代方案:为什么还值得学 wait/notify

因为 java.util.concurrent 底层大量使用它,比如 ArrayBlockingQueuetake()put()。看不懂 wait/notify,就看不懂这些类的阻塞逻辑、中断响应机制,也容易在自定义同步器中写出唤醒丢失的 bug。

容易被忽略的一点:wait() 会释放锁,但也会在返回前重新获取锁;而 LockSupport.park() 不涉及锁管理——两者语义不同,不能混用或随意替换。

真正在写新代码时,优先用 ReentrantLock.newCondition()BlockingQueue,但只要还在读 JDK 源码、维护老同步逻辑、或面试被问到,while + wait 就绕不开。

热门AI工具

更多
DeepSeek
DeepSeek

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

豆包大模型
豆包大模型

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

通义千问
通义千问

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

腾讯元宝
腾讯元宝

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

文心一言
文心一言

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

讯飞写作
讯飞写作

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

即梦AI
即梦AI

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

ChatGPT
ChatGPT

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

相关专题

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

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

806

2023.08.22

while的用法
while的用法

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

102

2023.09.25

java中break的作用
java中break的作用

本专题整合了java中break的用法教程,阅读专题下面的文章了解更多详细内容。

120

2025.10.15

java break和continue
java break和continue

本专题整合了java break和continue的区别相关内容,阅读专题下面的文章了解更多详细内容。

259

2025.10.24

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

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

653

2023.08.10

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

0

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

2

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

43

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

8

2026.02.12

热门下载

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

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
10分钟--Midjourney创作自己的漫画
10分钟--Midjourney创作自己的漫画

共1课时 | 0.1万人学习

Midjourney 关键词系列整合
Midjourney 关键词系列整合

共13课时 | 0.9万人学习

AI绘画教程
AI绘画教程

共2课时 | 0.2万人学习

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

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