首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java wait/notify 深度剖析:鎖釋放、喚醒機制、虛假喚醒與經典生產消費模式

     編輯:Java 相關知識

wait()/notify() 定義在 Object 中,意味著每個對象天然擁有監視器鎖與條件隊列。本文從底層語義切入,詳細闡述必須在 synchronized 中調用、wait 釋放鎖、notify 隨機喚醒、虛假喚醒需循環檢查等核心規則,並給出生產者-消費者交替打印的完整 Demo。

五大鐵律

  1. 屬於 Object,非 Thread;鎖屬於對象,操作鎖的方法自然屬於對象。
  2. 調用前必須持有該對象鎖 → 必須寫在 synchronized(obj) 塊中。
  3. wait() 釋放鎖,讓其他線程能進入同步塊調用 notify()。
  4. notify() 隨機喚醒一個等待線程;notifyAll() 喚醒所有,但只能搶到鎖的一個繼續執行。
  5. 喚醒後需重新獲取鎖,notify() 所在同步塊結束前,被喚醒線程仍處於阻塞狀態。

標準等待模板

synchronized(obj) {
    while (!condition) {      // 循環檢查防虛假喚醒
        obj.wait();           // 釋放鎖並進入條件隊列
    }
    // 條件滿足,執行業務邏輯
}

經典 Demo:子線程打印 10 次 → 主線程打印 100 次 → 循環 50 輪

class Business {
    private boolean isMainThread = true;

    public synchronized void sub(int i) {
        while (!isMainThread) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
        for (int j = 1; j <= 10; j++) System.out.println("sub thread " + j + ", loop " + i);
        isMainThread = false; notify();
    }

    public synchronized void main(int i) {
        while (isMainThread) { try { wait(); } catch (InterruptedException e) { e.printStackTrace(); } }
        for (int j = 1; j <= 100; j++) System.out.println("main thread " + j + ", loop " + i);
        isMainThread = true; notify();
    }
}

常見坑點提醒

  • 忘記 while 改用 if → 虛假喚醒導致邏輯錯誤。
  • 在非同步塊調用 → 拋出 IllegalMonitorStateException。
  • 業務邏輯過長持有鎖 → 降低並發度,應縮小同步範圍或改用 Condition。

掌握底層語義,靈活組合 synchronized + wait/notify 或升級至 Lock + Condition,即可構建高可靠的並發協作組件。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved