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

[java - wait() 虚假唤醒]

对!while (!isDone) { wait(); } 这个循环的核心作用就是防止“虚假唤醒”,这是多线程编程中一个非常重要的细节。

什么是“虚假唤醒”?

Java 中,线程调用 wait() 后可能会在没有被其他线程调用 notify()/notifyAll() 的情况下被唤醒,这种现象就是“虚假唤醒”(spurious wakeup)。
它不是程序错误导致的,而是操作系统或 JVM 内部的调度机制引起的(比如线程调度的“惊群效应”,或某些底层优化)。简单说:wait() 可能无缘无故地醒过来

为什么需要 while 循环来防虚假唤醒?

假设你把代码写成 if (!isDone) { wait(); }(用 if 而不是 while),会出现什么问题?

// 错误示例:用if判断,可能被虚假唤醒
public synchronized V get() throws Exception {if (!isDone) { wait(); // 若此处被虚假唤醒,直接跳出if}return result;
}
  • 正常情况:线程A执行完任务,调用 notifyAll(),主线程被唤醒,isDonetrue,返回结果——没问题。
  • 虚假唤醒情况:主线程在 wait() 时被无故唤醒,但此时 isDone 仍然为 false(任务根本没完成)。由于用了 if,只会判断一次,唤醒后直接跳出 if,返回 result(可能是 null 或错误值),导致逻辑错误。

while 循环如何解决问题?

while (!isDone) { wait(); } 时,每次线程从 wait() 中醒来(无论正常唤醒还是虚假唤醒),都会重新检查 isDone 的值

  • 如果是正常唤醒:isDone 已经被设为 true,循环条件不成立,跳出循环,返回正确结果。
  • 如果是虚假唤醒:isDone 仍然为 false,循环条件成立,会再次执行 wait() 继续阻塞,直到任务真的完成并被正常唤醒。

这就像你在等外卖时,每次被“敲门声”吵醒(无论真有人敲门还是听错了),都会先通过猫眼确认是不是外卖员(检查 isDone),不是的话就继续睡——确保不会白跑一趟。

结合你的代码,总结 while 循环的必要性

  • 你的 MyFutureTask 中,get() 方法的核心逻辑是“直到任务完成(isDone=true),才返回结果”。
  • 虚假唤醒会破坏这个逻辑(让线程在任务未完成时就继续执行)。
  • while 循环通过“唤醒后重新检查条件”,确保只有当 isDone 真的为 true 时,才会退出等待——完美解决虚假唤醒问题。

这也是 Java 官方文档中明确推荐的写法:永远在 while 循环中使用 wait(),而不是 if,目的就是防止虚假唤醒。

http://www.hn-smt.com/news/540/

相关文章:

  • 示性函数引入
  • 2025.10.27
  • 《程序员修炼之道:从小工到专家》笔记3
  • Day5div与span标签以及字体实体
  • CCUT应用OJ题解——贪吃的松鼠
  • Java流程控制——Scanner进阶使用
  • 结对编程心得
  • AI概念
  • 做题记录 #4
  • 20251027——读后感2
  • DeepSeek-DSA讲解
  • MCP和Function Calling的区别
  • CentOS7安装Miniconda
  • P14322 「ALFR Round 11」E 空崎ヒナ 题解 (markdown)
  • [题解]P7074 [CSP-J 2020] 方格取数
  • 二分查找边界
  • P3232 [HNOI2013] 游走
  • 软件工程学习日志2025.10.27
  • 深入解析:TCP/IP 四层模型协作流程详解
  • Windows全版本激活教程(仅供测试)
  • 10月27日
  • javascript构造对象数组向服务器端传输
  • 10.25 CSP-S 模拟赛
  • 鲜花10/27
  • 读《程序员的修炼之路:从小工到专家》有感
  • 想让默认头像不再千篇一律,就顺手复刻了一下 GitHub 的思路
  • java(3)基础规范
  • 读书日记3
  • Tuack 生成 OI 比赛题目 PDF 笔记
  • 数据库三大范式、Union和Union all的区别