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

Java 並發編程實戰:鎖分段技術實現高效能 StripedMap

     編輯:Java 綜合教學

鎖分段核心概念

鎖分段是一種降低鎖競爭、提高並發吞吐量的經典技術。核心思想:將資料結構分成多個段,每段獨立加鎖,不同段操作可並行執行。Java ConcurrentHashMap 即採用此設計。

StripedMap 實作解析

核心資料結構

public class StripedMap {
    private static final int N_LOCKS = 16; // 鎖條帶數量,通常為 2 的冪次
    private final Node[] buckets;          // 雜湊桶陣列
    private final Object[] locks;          // 鎖陣列,每個鎖守護一組桶
    
    private static class Node {
        String key, value;
        Node next; // 鏈表節點
    }
}

初始化邏輯

public StripedMap(int numBuckets) {
    buckets = new Node[numBuckets];
    locks = new Object[N_LOCKS];
    for (int i = 0; i < N_LOCKS; i++) {
        locks[i] = new Object(); // 每個鎖獨立物件
    }
}

雜湊與鎖映射

private final int hash(Object key) {
    return Math.abs(key.hashCode() % buckets.length);
}

// 關鍵:hash % N_LOCKS 決定使用哪把鎖
// 同一個 key 永遠映射到同一把鎖,保證線程安全

核心操作實作

get 操作

public Object get(Object key) {
    int hash = hash(key);
    // 只鎖住對應的段
    synchronized (locks[hash % N_LOCKS]) {
        for (Node m = buckets[hash]; m != null; m = m.next) {
            if (m.key.equals(key)) return m.value;
        }
    }
    return null;
}

clear 操作 - 分段清理

public void clear() {
    for (int i = 0; i < buckets.length; i++) {
        // 逐段加鎖清理,而非一次鎖住全部
        synchronized (locks[i % N_LOCKS]) {
            buckets[i] = null;
        }
    }
}

設計優勢分析

1. 降低鎖粒度

  • 單一全域鎖:所有操作串行,吞吐量受限於單核
  • 16 條帶鎖:理論上可支援 16 個執行緒並發讀寫不同段
  • 鎖競爭機率降低約 1/N_LOCKS

2. 靈活的擴展性

  • N_LOCKS 可根據 CPU 核心數調整 (通常 2 的冪次)
  • buckets 長度可獨立於鎖數量設定

3. 簡單有效的同步策略

  • 同一 key 的操作始終由同一把鎖保護,保證一致性
  • 無需複雜的無鎖演算法即可獲得高並發效能

對比與延伸

vs ConcurrentHashMap (JDK 7)

特性StripedMapConcurrentHashMap (JDK7)
Segment 數量固定 16 (N_LOCKS)預設 16 (concurrencyLevel)
鎖機制Object 陣列 + synchronizedReentrantLock + Segment 繼承
擴容支援無支援動態擴容
適用場景教學、簡易快取生產級高並發 Map

JDK 8 改進

JDK 8 ConcurrentHashMap 採用 CAS + synchronized + 紅黑樹,進一步降低鎖粒度到桶級別,並解決鏈表過長退化為 O(n) 查詢問題。

適用場景與注意事項

適用場景

  • 自訂快取實作
  • 計數器分片
  • 簡易並發 Map 需求
  • 教學理解分段鎖原理

注意事項

  1. 鎖數量固定:無法動態調整,高負載下可能成為瓶頸
  2. 無擴容機制:buckets 固定大小,負載因子不可控
  3. 複合操作非原子:如 check-then-act 需外部加鎖
  4. clear() 一致性:分段清理過程中 get 可能讀到舊資料

總結

StripedMap 以簡潔的程式碼展示了鎖分段的核心精髓:將單一鎖拆分為多把鎖,根據雜湊值分散鎖競爭。這是理解 ConcurrentHashMap、LongAdder、ThreadLocal 等高並發組件設計思想的基石。實際生產環境建議直接使用 JDK 提供的 ConcurrentHashMap、ConcurrentSkipListMap 等經過嚴格測試的並發集合。

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