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

Java 並發包鎖機制全解析:Lock、ReentrantLock、ReadWriteLock 實戰

     編輯:Java 綜合教學

synchronized 的局限性

  • 無法中斷等待:線程一旦進入阻塞狀態,只能等待鎖釋放或異常終止,無法響應 interrupt()。
  • 無法超時控制:不支援嘗試獲取鎖並設定等待上限。
  • 無法區分讀寫:多線程並發讀取時互斥,降低吞吐量。
  • 無法感知獲取狀態:無法判斷是否成功獲取鎖。
  • 釋放鎖時機固定:僅在代碼塊結束或異常拋出時自動釋放,靈活性不足。

Lock 接口核心方法

public interface Lock {
    void lock();                          // 阻塞獲取
    void lockInterruptibly() throws InterruptedException; // 可中斷獲取
    boolean tryLock();                    // 非阻塞嘗試
    boolean tryLock(long time, TimeUnit unit) throws InterruptedException; // 超時嘗試
    void unlock();                        // 釋放鎖
    Condition newCondition();             // 條件變量
}

ReentrantLock:可重入互斥鎖

實現 Lock,語義與 synchronized 相似但功能更強。支援公平/非公平模式(構造函數 new ReentrantLock(true))。

典型用法模板

Lock lock = new ReentrantLock();
public void safeMethod() {
    lock.lock();
    try {
        // 臨界區操作
    } finally {
        lock.unlock(); // 必須在 finally 中釋放
    }
}

ReadWriteLock:讀寫分離鎖

定義 readLock() 與 writeLock(),允許「讀讀共存、讀寫互斥、寫寫互斥」,大幅提升讀多寫少場景性能。

ReentrantReadWriteLock 進階特性

  • 可重入:同一線程可重複獲取讀/寫鎖。
  • 鎖降級:持有寫鎖 → 獲取讀鎖 → 釋放寫鎖(支援);反之不支援升級。
  • 公平策略可選:構造函數 new ReentrantReadWriteLock(true) 啟用公平模式。
  • 中斷響應:讀寫鎖均支援 lockInterruptibly()。

緩存場景實戰:雙重檢查鎖降級


class CacheDemo {
    private final Map<String, Object> map = new HashMap<>();
    private final ReadWriteLock rwl = new ReentrantReadWriteLock();
    private final Lock r = rwl.readLock();
    private final Lock w = rwl.writeLock();

    public Object getValue(String key) {
        r.lock();
        try {
            Object value = map.get(key);
            if (value == null) {
                r.unlock();                // 釋放讀鎖
                w.lock();                  // 獲取寫鎖
                try {
                    if (value == null) {   // 雙重檢查
                        value = loadFromDB(key);
                        map.put(key, value);
                    }
                } finally {
                    r.lock();              // 降級:先獲取讀鎖
                    w.unlock();            // 再釋放寫鎖
                }
            }
            return value;
        } finally {
            r.unlock();
        }
    }
}

Lock vs synchronized 選型指南

維度synchronizedLock
實現層級JVM 關鍵字API 接口
異常釋放自動手動(finally)
可中斷否是
超時獲取否是
公平鎖否(非公平)可選
條件變量Object.wait/notifyCondition(多條件)
讀寫分離無ReadWriteLock
性能(高競爭)較差優秀

四大核心鎖概念

  1. 可重入鎖:基於線程而非調用的分配機制,避免死鎖(synchronized、ReentrantLock)。
  2. 可中斷鎖:Lock.lockInterruptibly() 允許等待線程放棄等待處理其他任務。
  3. 公平鎖:嚴格按請求順序分配鎖,避免飢餓(ReentrantLock(true))。
  4. 讀寫鎖:分離讀寫操作,提升並發讀吞吐(ReadWriteLock)。

最佳實踐總結

  • 低競爭、簡單同步:優先 synchronized(JVM 優化好、代碼簡潔)。
  • 需中斷/超時/公平/多條件:必須用 Lock。
  • 讀多寫少、緩存、配置中心:ReadWriteLock 顯著提升性能。
  • 高並發寫入、低延遲要求:考慮 StampedLock(樂觀讀)或無鎖數據結構(ConcurrentHashMap、LongAdder)。
  • 鎖釋放必須放在 finally 塊,防止異常導致死鎖。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved