[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(),主線程被喚醒,isDone為true,返回結果——沒問題。 - 虛假喚醒情況:主線程在
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,目的就是防止虛假喚醒。

浙公網安備 33010602011771號