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

Java 多執行緒核心:線程安全與 synchronized 關鍵字深度解析

     編輯:Java 相關知識

何時發生線程安全問題?

單執行緒無安全問題。多執行緒同時存取共享資源(變數、物件、檔案、資料庫)且執行順序不可控時,可能導致結果與預期不符或程式崩潰。

經典案例:重複插入檢查

兩執行緒同時讀取資料 X → 同時檢查資料庫無 X → 同時插入 X → 產生重複資料。此時資料庫表為臨界資源。

解決核心:序列化存取臨界資源

採用同步互斥:同一時間僅允許一執行緒存取臨界資源。Java 提供兩種機制:synchronized 與 Lock。

synchronized 兩大使用形式

1. 同步方法

public synchronized void insert(Thread t) {
    for (int i=0; i<5; i++) {
        System.out.println(t.getName() + " 插入 " + i);
        list.add(i);
    }
}

效果:執行緒順序執行,Thread-0 完成後 Thread-1 才開始。

2. 同步程式碼塊

public void insert(Thread t) {
    synchronized (this) { // 或 synchronized (lockObject)
        // 僅此處同步,粒度更細
    }
}

優勢:僅同步必要區段,提升並發效能。

synchronized 關鍵規則

規則說明
一個物件一把鎖執行緒進入同步方法/塊需獲得物件鎖
同步方法互斥執行緒 A 在同步方法中,執行緒 B 無法進入同一物件的其他同步方法
非同步方法不受影響執行緒 B 仍可呼叫非同步方法
不同物件互不干擾物件 A 的同步方法不阻擋物件 B 的同步方法
異常自動釋放鎖JVM 保證異常時釋放鎖,不會死鎖

靜態同步與實例同步的區別

public synchronized void instanceMethod() { ... }        // 鎖:this (實例)
public static synchronized void staticMethod() { ... }   // 鎖:Class 物件
  • 實例同步鎖住當前實例
  • 靜態同步鎖住Class 物件(所有實例共用)
  • 兩者互不阻塞:一執行緒進實例同步,另一執行緒可進靜態同步

位元碼層面原理

  • 同步方法:方法資訊標記 ACC_SYNCHRONIZED,JVM 自動進入/退出時獲取/釋放鎖
  • 同步塊:編譯為 monitorenter / monitorexit 指令對,對應鎖計數器 +1/-1

synchronized 進階注意事項

  1. 不可繼承:子類覆寫父類同步方法不會自動同步,需重新加 synchronized
  2. 避免鎖住不可變物件:String、Integer 等常量池物件可能導致非預期共享鎖
  3. 粒度越小越好:優先用同步塊鎖住關鍵區段,而非整個方法
  4. 死鎖預防:固定鎖獲取順序、使用 tryLock(timeout)(需 Lock 介面)

效能優化建議

  • JDK 1.6+ 引入偏向鎖、輕量級鎖、鎖消除、鎖粗化等優化,synchronized 效能已大幅提升
  • 高併發場景考慮 ReentrantLock(公平鎖、可中斷、條件變數)
  • 讀多寫少用 ReentrantReadWriteLock 或 StampedLock
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved