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

Java 多執行緒核心:線程間通訊的三大機制深度解析

     編輯:Java 相關知識

在多執行緒程式設計中,線程間通訊是協調任務、共享資料的關鍵。Java 提供了多種機制,從基礎的 synchronized 到進階的 wait/notify,各有適用場景與優缺點。本文透過程式碼實戰,深度剖析三種主流通訊方式的原理、陷阱與最佳實踐。

一、同步鎖通訊:共享記憶體模型

利用 synchronized 關鍵字鎖定共享物件,實現「同一時間僅一執行緒存取關鍵區段」。本質是共享記憶體通訊:誰拿到鎖,誰就能讀寫共享變數,其他執行緒阻塞等待。

public class SharedObject {
    public synchronized void methodA() { /* 任務 A */ }
    public synchronized void methodB() { /* 任務 B */ }
}

// 線程 A 呼叫 methodA(),線程 B 呼叫 methodB()
// 因鎖定同一 SharedObject 實例,B 必須等 A 釋放鎖才能進入 methodB()

優點:語法簡單、JVM 原生支援、適用於互斥存取。
缺點:粗粒度鎖導致並發度低;無法實現「條件等待」(如:等待隊列非空),只能無條件阻塞。

二、輪詢機制:以時間換空間的笨拙方案

執行緒 B 不斷在 while(true) 迴圈中檢查條件(如 list.size() == 5),條件滿足才執行後續邏輯。

// 線程 B:消耗 CPU 的無效輪詢
while (true) {
    if (sharedList.size() == 5) {
        System.out.println("條件滿足,準備處理");
        break; // 或拋出異常跳出
    }
}

致命缺陷:空轉消耗 CPU。JVM 分配時間片給線程 B,它卻只做條件判斷,不執行實質工作。如同「盯著手機螢幕等電話」,極度浪費算力。生產環境嚴禁使用。

三、wait/notify 機制:高效的條件等待與通知

基於 Object 類的 wait()、notify()、notifyAll(),實現「條件不滿足 → 釋放鎖進入 WAITING 狀態 → 條件滿足 → 被喚醒進入 RUNNABLE 狀態」的優雅協作。

// 共享鎖物件
Object lock = new Object();

// 線程 A:等待條件
synchronized (lock) {
    while (list.size() != 5) { // 必須用 while 防止虛假喚醒
        lock.wait(); // 釋放鎖,進入等待集合
    }
    // 條件滿足,繼續執行
}

// 線程 B:改變條件並通知
synchronized (lock) {
    for (int i = 0; i < 10; i++) {
        list.add("item");
        if (list.size() == 5) {
            lock.notify(); // 喚醒一個等待線程
        }
    }
}

核心規則(必背)

  1. 必須在 synchronized 區塊內呼叫:否則拋 IllegalMonitorStateException。
  2. wait() 釋放鎖,sleep() 不釋放鎖。
  3. 用 while 而非 if 檢查條件:防止虛假喚醒(spurious wakeup)與通知遺失。
  4. notify() 隨機喚醒一個,notifyAll() 喚醒全部(推薦,避免信號遺漏)。

經典陷阱:通知過早

若線程 B 先執行,notify() 發出時線程 A 尚未 wait(),信號丟失。線程 A 後續 wait() 將永久阻塞。
解決:引入狀態標誌位(如 boolean ready = false),線程 B 設置 ready = true 後再 notify();線程 A 檢查 while(!ready) wait()。這正是 Condition / BlockingQueue 內部的設計思想。

四、現代替代方案:別再手寫 wait/notify

JDK 1.5+ java.util.concurrent 提供更高階、更安全的工具:

  • BlockingQueue(ArrayBlockingQueue、LinkedBlockingQueue):生產者-消費者首選,內建阻塞與等待。
  • CountDownLatch / CyclicBarrier:多線程同步屏障。
  • CompletableFuture:非同步編排,鏈式回調。
  • Lock + Condition:ReentrantLock 配合 newCondition(),支援多條件隊列,比 wait/notify 靈活。
// 生產者-消費者標準寫法
BlockingQueue<Task> queue = new LinkedBlockingQueue<>();

// 生產者
queue.put(task); // 滿則阻塞

// 消費者
Task t = queue.take(); // 空則阻塞

五、總結對比

機制核心原理CPU 效率適用場景推薦指數
synchronized互斥鎖中簡單互斥、臨界區保護⭐⭐⭐
輪詢忙等待極低教學演示、極簡單場景❌ 禁用
wait/notify條件等待/通知高底層框架開發、特定協作⭐⭐
BlockingQueue 等高階並發組件高業務開發、生產者消費者、任務編排⭐⭐⭐⭐⭐

掌握 wait/notify 原理是理解 JUC 組件的基石,但實戰中請優先選用 BlockingQueue、CompletableFuture 等成熟組件,讓專家幫你處理邊界條件與記憶體可見性。

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