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

Java 同步機制深度對比:synchronized 同步塊/方法 vs volatile 變量,原理與選型指南

     編輯:Java 綜合教學

兩大內建同步機制

  • synchronized:互斥鎖,提供原子性 + 可見性 + 有序性,適用於臨界區、複合操作。
  • volatile:輕量級同步,提供可見性 + 有序性 (禁止指令重排),不保證原子性,適用於單次讀寫、狀態標記。

synchronized 四種形式

形式鎖對象並發粒度適用場景
實例方法this (當前實例)同一實例串行實例級臨界區
靜態方法Class 對象 (如 MyClass.class)類級串行 (所有實例共享)靜態變量操作、單例初始化
實例方法同步塊synchronized(this) 或自定義對象同步塊內串行縮小鎖範圍、提高並發
靜態方法同步塊synchronized(MyClass.class)類級串行靜態資源保護

代碼示範

public class Counter {
    private long count = 0;
    // 實例方法同步
    public synchronized void add(long v) { count += v; }
    // 同步塊縮小範圍
    public void add2(long v) { synchronized(this) { count += v; } }
    // 靜態同步
    private static long staticCount = 0;
    public static synchronized void staticAdd(long v) { staticCount += v; }
    public static void staticAdd2(long v) { synchronized(Counter.class) { staticCount += v; } }
}

volatile 語義與實現原理

class VolatileDemo {
    volatile long v = 0L;        // 單次讀寫具有原子性 (含 64 位 long/double)
    public void set(long x) { v = x; }           // volatile 寫
    public long get() { return v; }              // volatile 讀
    public void inc() { v++; }                   // 復合操作:讀-改-寫,非原子!
}

編譯器將 volatile 讀寫插入內存屏障:

  • 寫屏障:確保前面指令不重排到寫後,刷新緩存到主內存。
  • 讀屏障:確保後面指令不重排到讀前,失效本地緩存重新從主內存讀取。

等價於對每次單次讀寫加同一把監視器鎖 (但無互斥,無上下文切換開銷)。

核心差異總結

選型決策樹

  1. 需保護多步復合操作 (如 i++、先檢查後更新) → synchronized / Lock / AtomicInteger。
  2. 單一變量狀態標記 (如 boolean closed、long timestamp)、單次讀寫、一寫多讀 → volatile。
  3. 高併發計數器 → LongAdder / AtomicLong (CAS 無鎖)。
  4. 雙重檢查鎖單例 → volatile 修飾實例引用 + synchronized 保護構造。

常見錯誤

  • 用 volatile 保護 count++ → 非原子,並發下計數丟失。
  • synchronized 鎖字符串常量 / 包裝類對象 → 不同實例可能指向同一常量池對象,導致誤共享。
  • 同步塊中調用耗時 IO/睡眠 → 持鎖時間過長,嚴重降低吞吐。

總結

synchronized 是重型武器,解決「互斥 + 可見 + 有序」全套問題;volatile 是輕型利器,專治「可見 + 有序」,不解決原子性。實戰中常配合使用:volatile 狀態標記 + synchronized 復合操作,或直接用 java.util.concurrent 原子類/鎖/集合獲得更好性能與語義。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
維度synchronizedvolatile
原子性✅ (臨界區串行)❌ (僅單次讀寫原子,復合非原子)
可見性✅ (解鎖前刷新、加鎖後失效)✅ (內存屏障)
有序性✅ (鎖內串行)✅ (禁止重排)
阻塞可能阻塞、上下文切換不阻塞、無切換
適用對象任意對象/類只能修飾字段 (含靜態/實例)
性能較重 (JDK 6+ 優化:偏向鎖/輕量級鎖/鎖消除/鎖粗化)極輕 (近似普通讀寫 + 屏障)