当前位置: 首页 > news >正文

为什么 wait() / notify() 必须在同步代码块 / 同步方法中调用

目录

一、先搞懂基础

二、核心原因(3 点)

1. 防止 丢失唤醒(Lost Wake-Up)(最关键)

错误时序(无锁场景)

加锁后(同步块),时序被原子化

2. JVM 语法强制:必须持有对象监视器

3. 保证等待 / 唤醒逻辑的线程安全

三、补充最佳实践(面试常考)

面试极简背诵版


一句话结论:为了规避「丢失唤醒」并发 bug,同时保证线程安全、语义合法,JVM 强制要求必须持有对象锁才能调用。

一、先搞懂基础

  1. wait()notify()notifyAll()Object 类方法,作用于对象监视器(锁)
  2. 调用obj.wait():当前线程释放 obj 锁,进入该对象的等待集阻塞,等待被唤醒。
  3. 调用obj.notify():随机唤醒等待集中一个线程;notifyAll()唤醒全部。

二、核心原因(3 点)

1. 防止丢失唤醒(Lost Wake-Up)(最关键)

这是设计层面的根本原因,先看不在同步块会出现的致命问题:

错误时序(无锁场景)

假设业务逻辑:条件不满足 → 等待;条件满足 → 唤醒

  1. 线程 A:判断条件不成立,正要执行wait()
  2. CPU 切换到线程 B
  3. 线程 B:修改数据,条件成立,执行notify()唤醒 →此时线程 A 还没进入等待队列,这次唤醒直接作废
  4. CPU 切回线程 A:继续执行wait()→ 线程 A 永久阻塞,永远没人再唤醒它(丢失唤醒)
加锁后(同步块),时序被原子化

锁保证「条件判断 + wait ()」是原子操作

  1. 线程 A 获取锁 → 判断条件不成立
  2. 直接执行wait()原子完成,中间不会被打断
  3. 线程 B 必须等 A 释放锁后才能进入、修改条件、notify 彻底杜绝「先唤醒、后等待」的丢失唤醒问题。

2. JVM 语法强制:必须持有对象监视器

JVM 规范规定:

调用wait()/notify()时,当前线程必须持有该 Object 的内置锁

如果没有持有锁直接调用,会立刻抛出:

java.lang.IllegalMonitorStateException

原因:

  • wait()语义是 **“拿着锁,主动放弃锁并等待”**;
  • 没有锁,就不存在「放弃锁」这个动作,语义不成立。

3. 保证等待 / 唤醒逻辑的线程安全

等待一般都伴随共享变量条件判断(比如队列空 / 满、状态标志):

  • 共享变量本身就存在并发竞争,必须加锁保证可见性、原子性
  • 同步块天然保证:变量状态在线程间及时可见,避免因指令重排、内存可见性导致逻辑错乱。

三、补充最佳实践(面试常考)

  1. wait()一定要放在while循环里防止虚假唤醒(线程可能在无 notify 时被意外唤醒):
    synchronized (obj) { while (条件不满足) { obj.wait(); } // 执行业务 }
  2. notify()/notifyAll()也必须在同一个对象锁的同步块中。
  3. 优先用notifyAll(),多数场景下更安全。

面试极简背诵版

  1. 防止丢失唤醒:锁让「条件判断 + wait」原子执行,避免唤醒先于等待发生;
  2. JVM 强制校验:调用这两个方法必须持有对象监视器,否则抛IllegalMonitorStateException
  3. 保证线程安全:同步锁保障条件变量的可见性与原子性。
http://www.rkmt.cn/news/1436934.html

相关文章:

  • 从零搭建本地RAG知识库,你的文档终于能自己回答问题了!从安装到测试全流程讲解!
  • 2026 屋面露台防水综合排行榜 苏易修缮防水全域应急抢修连锁评选 - 吉修匠
  • 解放你的音乐收藏:ncmdumpGUI让网易云音乐NCM文件随处播放的终极指南
  • Linux文件‘捉迷藏’实战:5分钟掌握find与grep的日常高效用法(附场景案例)
  • 终极D2DX宽屏补丁:如何让经典《暗黑破坏神2》在现代PC上完美运行
  • 2026年安徽省初三成绩在300分左右适合上什么学校?——推荐合肥理工学校 - 教育为先
  • 合肥市初三毕业生考不上高中适合上什么学校?——最新发布推荐学校一览 - 教育为先
  • 客制化键盘改造:3D打印拇指扩展键,提升输入效率与人体工学体验
  • Win-PS2EXE:3步快速将PowerShell脚本编译成EXE的终极图形化工具
  • 免费的pdf合并工具推荐?2026免费无水印PDF合并软件汇总 - 科技大爆炸
  • 基于 Harmony 6.0 应用的跑腿代购服务平台首页实现
  • 番茄小说下载器:5分钟搭建个人永久书库的完整指南
  • 基于ESP8266与Arduino Nano的恩尼格玛密码机硬件实现
  • 鸣潮自动化终极指南:释放你的游戏时间,让AI帮你刷日常
  • 抖音视频批量下载终极指南:douyin-downloader让内容创作效率提升300%
  • |南京防水补漏公司推荐|2026 本地靠谱正规品牌榜单 - 吉修匠
  • 基于Arduino Nano自制AVR ISP编程器:硬件设计、软件配置与实战烧录指南
  • 保姆级教程:在Ubuntu 22.04上从下载到流畅运行CLion 2022.2.5的全记录
  • 室内烟雾明火检测数据集VOC+YOLO格式2469张2类别
  • ppt转pdf不压缩画质的工具推荐?2026PPT转PDF画质无损方法 - 科技大爆炸
  • 终极指南:如何快速使用Pearcleaner彻底清理你的Mac应用
  • 别再手动抠窗户了!3dMax 2016+用PolyWindow插件,5分钟搞定异形窗建模
  • 在Windows上打造专业级B站体验:BiliBili-UWP客户端深度解析
  • 低场MRI永磁体阵列设计与磁场均匀性优化
  • Ansys学习-静力学-day6
  • 2026南京屋顶漏水渗水治理 同城防水修缮高实力榜单推荐靠谱团队 - 吉修匠
  • 基于TDA2030A的DIY音频功放制作:从电路设计到调试全解析
  • Typed Assembly Language在密码学软件安全中的应用与优化
  • 真实Agent迭代案例,真正理解Harness工程
  • 如何永久备份微信聊天记录:WeChatMsg完整本地化解决方案指南