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

Java 並發編程深度解析:Synchronized 關鍵字原理與實戰應用

     編輯:Java 綜合教學

Java 並發核心:Synchronized 實現原理與最佳實踐

synchronized 是 Java 中解決並發問題最基礎、最常用的同步機制。它不僅能確保線程互斥訪問同步代碼,還能保證共享變量的內存可見性,並有效解決指令重排序問題。本文將從基本用法、底層原理、實戰案例三個維度深度解析。

一、Synchronized 三種基本用法

1. 修飾實例方法

public synchronized void instanceMethod() {
    // 同步代碼塊
    // 鎖對象:當前實例 (this)
}

鎖住的是當前對象實例 this。同一實例的不同同步方法互斥,不同實例互不影響。

2. 修飾靜態方法

public static synchronized void staticMethod() {
    // 鎖對象:當前類的 Class 對象
}

鎖住的是類級別的 Class 對象。所有實例共享同一把鎖,屬於類級別同步。

3. 修飾代碼塊

public void blockSync() {
    synchronized (this) { // 或自定義鎖對象
        // 精確控制同步範圍
    }
}

靈活指定鎖對象,可縮小同步範圍,提升並發性能。

二、實戰案例對比

案例 1:無同步 - 並發執行

public class SyncDemo {
    public void method1() { /* 耗時 3秒 */ }
    public void method2() { /* 耗時 1秒 */ }

    public static void main(String[] args) {
        SyncDemo demo = new SyncDemo();
        new Thread(() -> demo.method1()).start();
        new Thread(() -> demo.method2()).start();
    }
}

輸出:Method 1 start → Method 1 execute → Method 2 start → Method 2 execute → Method 2 end → Method 1 end
分析:兩線程並發執行,互不阻塞。

案例 2:實例方法同步 - 串行執行

public synchronized void method1() { ... }
public synchronized void method2() { ... }

輸出:Method 1 完全結束後,Method 2 才開始
分析:同一實例的兩個同步方法共享 this 鎖,互斥執行。

案例 3:靜態方法同步 - 類級別串行

public static synchronized void method1() { ... }
public static synchronized void method2() { ... }
// 主方法中創建兩個不同實例 test 和 test2

輸出:仍然串行執行
分析:靜態方法鎖的是 SyncDemo.class,與實例無關。

案例 4:同步代碼塊 - 精確控制

public void method1() {
    System.out.println("Method 1 start");
    synchronized (this) {
        System.out.println("Method 1 execute");
        Thread.sleep(3000);
    }
    System.out.println("Method 1 end");
}

輸出:Method 1 start → Method 1 execute → Method 2 start → Method 1 end → Method 2 execute → Method 2 end
分析:非同步代碼可並發,只有進入同步塊時才阻塞。

三、底層實現原理:Monitor 鎖機制

通過 javap -c 反編譯查看字節碼:

同步代碼塊

monitorenter  // 進入監視器
// 同步代碼
monitorexit   // 退出監視器

同步方法

ACC_SYNCHRONIZED 標誌位
// 無 monitorenter/monitorexit,由 JVM 通過方法標誌隱式實現

Monitor 核心規則

  • 每個對象關聯一個 Monitor,Monitor 可被線程擁有
  • monitorenter:嘗試獲取所有權
    • 計數器為 0 → 進入,計數器置 1,成為擁有者
    • 已是擁有者 → 重入,計數器 +1
    • 被其他線程佔用 → 阻塞等待
  • monitorexit:釋放所有權
    • 計數器 -1,若為 0 → 釋放鎖,喚醒等待線程

這就是為什麼 wait()/notify() 必須在同步塊中調用的原因——它們依賴 Monitor 對象。

四、運行結果深度解析

案例鎖對象執行模式核心原因
實例方法同步同一實例 (this)串行競爭同一把對象鎖
靜態方法同步Class 對象串行不同實例共享類鎖
同步代碼塊括號內對象部分串行僅同步塊互斥,外部並發

五、總結與最佳實踐

  1. 優先縮小同步範圍:使用同步代碼塊而非整個方法
  2. 避免使用 String 常量作為鎖:常量池導致不同類共享同一把鎖
  3. 理解鎖升級:偏向鎖 → 輕量級鎖 → 重量級鎖 (JDK 1.6+ 優化)
  4. 考慮替代方案:ReentrantLock、volatile、Atomic 類、無鎖算法

深入理解 Synchronized 的 Monitor 機制,不僅能幫助正確使用同步關鍵字,更能從根本上理解 Java 並發編程的核心模型,為選擇最優並發策略奠定基礎。

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