wait/notify 是 Java 同步機制的基石,構建生產者-消費者、線程池、鎖框架的核心原語。本文從狀態變量、條件斷言、條件隊列三大概念切入,嚴謹定義 wait/notify/notifyAll 的語義規則,給出循環檢查模板並針對虛假喚醒、多條件共享鎖、多線程競爭三大場景深度剖析循環的必要性。
queue.size() < capacity)。wait() 將當前線程加入,notify() 從中喚醒。Object,每個對象天然擁有鎖與條件隊列。synchronized(obj) 中。wait() 釋放鎖並進入條件隊列;notify() 隨機喚醒一個;notifyAll() 喚醒全部。wait() 之後的代碼。notify() 執行時鎖仍被持有,被喚醒線程只能在鎖釋放後競爭。synchronized(obj) {
while (!conditionPredicate) { // 循環而非 if
obj.wait(); // 釋放鎖、進隊列、掛起
}
// 條件滿足,安全執行業務邏輯
}
| 場景 | 若用 if 後果 | while 保護機制 |
|---|---|---|
| 一把鎖保護多狀態變量 | 被喚醒線程可能檢查錯誤條件,繼續執行導致邏輯錯誤 | 醒來重新檢查自身條件,不滿足繼續 wait |
| 多線程等待同一條件 | notifyAll 喚醒所有,只有一個能搶到資源,其餘若不檢查會錯誤執行 | 搶不到資源的線程檢查失敗,繼續 wait |
| 虛假喚醒 | 無故醒來直接執行業務邏輯,嚴重 Bug | 條件不滿足,循環回去 wait |
JDK 1.5+ 推薦使用 Lock + Condition:
Lock lock = new ReentrantLock(); Condition notFull = lock.newCondition();
精確綁定條件隊列,避免多條件共用一把鎖的混淆,API 更語義化。
掌握 Wait-Notify 本質,是通往高性能並發組件開發的必經之路。