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

Java 多線程編程:ReadWriteLock 讀寫鎖深度解析與實戰

     編輯:Java 相關知識

ReadWriteLock 核心機制

ReadWriteLock 維護一對鎖:讀鎖(共享鎖)與 寫鎖(排他鎖)。

  • 讀-讀:不互斥,多線程可並發讀取。
  • 讀-寫 / 寫-讀 / 寫-寫:互斥,寫操作獨佔資源。

適用於「讀多寫少」的共享數據場景,顯著提升並發吞吐量。

基本用法示例

public class ReadWriteLockDemo {
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private Object data;

    public Object read() {
        readLock.lock();
        try {
            // 模擬讀取耗時
            Thread.sleep((long) (Math.random() * 100));
            return data;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return null;
        } finally {
            readLock.unlock();
        }
    }

    public void write(Object newData) {
        writeLock.lock();
        try {
            // 模擬寫入耗時
            Thread.sleep((long) (Math.random() * 100));
            this.data = newData;
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
        } finally {
            writeLock.unlock();
        }
    }
}

進階應用:線程安全緩存實現

public class Cache {
    private final Map cache = new HashMap<>();
    private final ReadWriteLock rwLock = new ReentrantReadWriteLock();
    private final Lock readLock = rwLock.readLock();
    private final Lock writeLock = rwLock.writeLock();
    private final Function loader; // 數據加載器(如查數據庫)

    public Cache(Function loader) {
        this.loader = loader;
    }

    public V get(K key) {
        // 1. 嘗試讀鎖快速讀取
        readLock.lock();
        try {
            V value = cache.get(key);
            if (value != null) return value;
        } finally {
            readLock.unlock();
        }

        // 2. 升級為寫鎖(雙重檢查鎖定模式)
        writeLock.lock();
        try {
            // 再次檢查,防止多線程並發加載同一 key
            V value = cache.get(key);
            if (value == null) {
                value = loader.apply(key); // 昂貴操作:查 DB、遠程調用等
                cache.put(key, value);
            }
            return value;
        } finally {
            writeLock.unlock();
        }
    }

    public void invalidate(K key) {
        writeLock.lock();
        try {
            cache.remove(key);
        } finally {
            writeLock.unlock();
        }
    }
}

關鍵注意事項

  • 必須在 finally 中釋放鎖,防止異常導致死鎖。
  • 避免在持有讀鎖時獲取寫鎖(會死鎖),需先釋放讀鎖再獲取寫鎖(如緩存示例)。
  • 公平性:ReentrantReadWriteLock 默認非公平,可構造時指定 true 為公平模式。
  • 鎖降級:支持從寫鎖降級為讀鎖(先獲取寫鎖,再獲取讀鎖,釋放寫鎖),但不支持升級。

性能對比

在 8 核機器上,讀寫比 9:1 時,ReadWriteLock 吞吐量約為 synchronized 的 3-5 倍;寫操作佔比超過 30% 時優勢明顯縮小,甚至不如獨占鎖。

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