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

Java 線程安全核心總結:JMM、synchronized、volatile、生產者消費者模式

     編輯:Java 相關知識

前言

線程安全本質是控制多線程對共享資源的**有序訪問**與**可見性**。本文從 JVM 記憶體模型 (JMM) 出發,系統梳理 synchronized、volatile、wait/notify 核心機制,並以經典生產者-消費者模式為例展示實戰應用。

一、JVM 記憶體模型 (JMM) 基石

主記憶體與工作記憶體

  • 主記憶體:所有線程共享,存放實例對象、靜態欄位、數組元素。
  • 工作記憶體:每線程私有,存放主存變數副本 (對應 CPU 寄存器 + L1/L2 快取)。

八大原子操作

read (主存→工作存)    load (載入工作存)
use  (工作存→引擎運算) assign (運算結果→工作存)
store (工作存→主存)    write (寫入主存)
lock (主存加鎖)        unlock (主存解鎖)

JMM 規範這些操作的順序與可見性,屏蔽底層硬體/OS 差異。

核心問題:可見性與有序性

  • 可見性:線程 A 修改共享變數,線程 B 能否立即看到?
    → 工作記憶體隔離導致「髒讀」。
  • 有序性:程序順序 vs 執行順序。
    → 編譯器優化、CPU 指令重排、快取回寫延遲導致亂序。

二、synchronized:重量級互斥鎖 (JDK 1.6+ 鎖升級優化)

語法形式

volatile int i = 0;
i++; // 讀-改-寫三步,非原子!多線程下會丟失更新

適用場景 (雙重檢查)

  1. 寫入不依賴當前值 (單純賦值、狀態標記)。
  2. 不參與不變式約束 (無多變量協同)。
class Plate {
    private final List eggs = new ArrayList<>();
    private final int capacity = 1;

    public synchronized Object take() throws InterruptedException {
        while (eggs.isEmpty()) wait(); // 條件不滿足等待
        Object egg = eggs.remove(0);
        notify(); // 喚醒生產者
        return egg;
    }

    public synchronized void put(Object egg) throws InterruptedException {
        while (eggs.size() >= capacity) wait();
        eggs.add(egg);
        notify(); // 喚醒消費者
    }
}

class Producer implements Runnable {
    private final Plate plate;
    Producer(Plate p) { this.plate = p; }
    public void run() {
        for (int i=0; i<5; i++) {
            plate.put(new Object()); // 模擬生產
            sleepRandom();
        }
    }
}

class Consumer implements Runnable {
    private final Plate plate;
    Consumer(Plate p) { this.plate = p; }
    public void run() {
        for (int i=0; i<5; i++) {
            plate.take(); // 模擬消費
            sleepRandom();
        }
    }
    void sleepRandom() { try { Thread.sleep((long)(Math.random()*1000)); } catch (InterruptedException e) {} }
}


五、進階:阻塞隊列 BlockingQueue 取代手工 wait/notify

    機制原子性可見性有序性適用場景
    synchronized✅✅✅複雜臨界區、複合操作、需互斥
    volatile❌✅✅狀態旗標、單次發布、獨立觀察
    Atomic* / LongAdder✅ (CAS)✅✅計數器、累加器、單變量原子更新
    ReentrantLock✅✅✅需可中斷、超時、公平、多條件
    BlockingQueue✅✅✅生產消費、任務調度、線程池工作隊列


最佳實務

  1. 優先使用 **線程安全集合 / BlockingQueue / Atomic 類**,減少手工同步。
  2. 必須手工同步時,**鎖粒度最小化**、**持鎖時間最短化**、**避免持鎖調用外部方法**。
  3. volatile 僅用於**單寫單讀/多讀單寫**獨立變量,複雜邏輯用 synchronized。
  4. 掌握 **JMM happens-before 規則**:程序順序、鎖規則、volatile 規則、線程啟動/終止、傳遞性。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved