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

Java 線程核心:共享數據訪問與同步機制深度解析

     編輯:Java 相關知識

多線程協作的核心難題在於共享數據的正確訪問。Java 提供 volatile 與 synchronized 兩大關鍵字,分別解決可見性與原子性+可見性。本文系統講解線程內存模型、鎖機制、同步粒度選擇、線程安全集合包裝等實戰知識。

共享變量與內存可見性陷阱

所有線程共享堆內存(靜態字段、實例字段、數組元素)。但現代 CPU 為了性能引入緩存、寄存器、指令重排,導致:

  • 線程 A 寫入變量,線程 B 可能讀到舊值(緩存未刷新)
  • 相關變量更新順序被打亂,線程觀測到中間態

示例:計時器線程置 finished=true,計算線程輪詢該標誌。若無 volatile,計算線程可能永遠看不到更新,陷入死循環。

volatile:輕量級可見性保證

  • 強制讀寫直接穿透 CPU 緩存,直達主內存
  • 禁止指令重排優化(JMM happens-before 語義)
  • 僅適用於單個基本類型/引用變量,不保證複合操作原子性(如 volatile int i; i++ 仍非原子)

synchronized:鎖與原子代碼塊

雙重語義

  1. 互斥:同一時間僅一線程持有鎖,進入受保護塊
  2. 可見性:鎖釋放前將寫入刷新主內存,獲取鎖時使本地緩存失效

鎖對象身份決定保護範圍

// 實例方法鎖 this
public synchronized void setXY(int x, int y) { ... }

// 等價塊
public void setXY(int x, int y) { synchronized(this) { ... } }

// 靜態方法鎖 Class 對象
public static synchronized void staticMethod() { ... }

// 顯式指定鎖
private final Object lock = new Object();
public void method() { synchronized(lock) { ... } }

關鍵認知:鎖保護的是「代碼塊進入權」,而非變量本身。不同實例調用同步方法互不阻塞;同一實例不同同步方法互斥。

同步最佳實踐

原則說明
縮小同步範圍僅保護必要的共享狀態操作,避免 I/O、睡眠在鎖內
不保護局部變量棧上私有,天然線程安全
優先用 JDK 線程安全類ConcurrentHashMap、CopyOnWriteArrayList、AtomicInteger 等
集合包裝器Collections.synchronizedMap/List/Set 為非安全集合加鎖

實戰案例:線程安全簡易緩存

public class SimpleCache {
    private final Map cache = new HashMap<>();

    public Object getObject(String key) {
        synchronized (cache) {  // 以 cache 作為鎖
            Object val = cache.get(key);
            if (val == null) {
                val = load(key);  // 昂貴操作在鎖內,簡單但降低併發度
                cache.put(key, val);
            }
            return val;
        }
    }
    public void clearCache() { synchronized (cache) { cache.clear(); } }
}

改進方向:雙重檢查鎖、ConcurrentHashMap.computeIfAbsent、FutureTask 避免重複加載。

常見誤區

  • Vector/Hashtable 方法雖同步,但複合操作(如「檢查後取」)仍需外部加鎖
  • 文檔未聲明線程安全 → 必須假設不安全
  • 過度同步導致死鎖、性能崩潰

總結

理解 JMM 可見性與原子性區別,volatile 管單變量發布,synchronized 管臨界區原子性。實戰中優先用 java.util.concurrent 成熟組件,僅在必要時手寫同步,並嚴守「鎖保護狀態、狀態決定鎖」設計原則。

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