Map系列之ConcurrentHashMap源碼分析:高并發場景下的性能密碼

引言:當線程安全成為剛需

1.1 并發時代的Map困境

  • 經典案例:電商秒殺系統超賣事故分析(附線程堆棧截圖)
  • 傳統方案缺陷:synchronizedMap的吞吐量陷阱(JMH測試數據對比)
  • ConcurrentHashMap的定位:高并發場景下的"瑞士軍刀"

1.2 版本演進時間線

JDK版本核心改進性能提升幅度
1.5分段鎖架構5.8倍
1.8CAS+synchronized混合鎖3.2倍
1.9+Node數組動態擴容19%

一、架構解密:ConcurrentHashMap核心設計

1.1 數據結構演進

1.1.1 Node數組進化史
// JDK1.8 Node結構
static class Node<K,V> implements Map.Entry<K,V> {final int hash;final K key;volatile V val;volatile Node<K,V> next;
}
  • CAS進化:從分段鎖到CAS+synchronized的混合鎖機制
  • 紅黑樹優化:鏈表轉樹閾值從8調整到6(JDK1.8.0_302)
1.1.2 動態擴容機制
// 擴容觸發條件(JDK1.8)
final void tryPresize(int size) {int c = (size >= (MAXIMUM_CAPACITY >>> 1)) ? MAXIMUM_CAPACITY : tableSizeFor(size + (size >>> 1) + 1);int sc = resizeStamp(n) << RESIZE_STAMP_SHIFT;while (!U.compareAndSwapInt(this, SIZECTL, sc, -1)) {// CAS擴容控制}// ...擴容邏輯...
}
  • 雙緩沖擴容:transferIndex分段遷移策略
  • 協助擴容:擴容期間其他線程可參與數據遷移

二、并發控制:鎖的精密舞蹈

2.1 鎖分段技術演進

2.1.1 分段鎖(JDK1.5)
// Segment結構(已廢棄)
static final class Segment<K,V> extends ReentrantLock {transient volatile HashEntry<K,V>[] table;
}
  • 優勢:減少鎖粒度
  • 缺陷:內存占用增加50%
2.1.2 混合鎖(JDK1.8+)
// putVal方法核心邏輯
final V putVal(K key, V value, boolean onlyIfAbsent) {if ((tab = table) == null || (n = tab.length) == 0)n = (tab = resize()).length;if ((p = tab[i = (n - 1) & hash]) == null)// CAS插入新節點else if ((fh = p.hash) >= 0) {// synchronized鎖定當前桶}// ...紅黑樹處理邏輯...
}
  • 鎖升級機制:從CAS到synchronized的漸進式加鎖
  • 無鎖讀取:volatile變量保證可見性

2.2 并發操作全解析

2.2.1 size()方法實現
// 映射計數原理
public int size() {long n = sumCount();return ((n < 0L) ? 0 : (n >= Long.MAX_VALUE) ? Long.MAX_VALUE : n);
}// sumCount方法
final long sumCount() {CounterCell[] as = counterCells; // 分離計數數組CounterCell a;long sum = baseCount;if (as != null) {for (int i = 0; i < as.length; ++i) {if ((a = as[i]) != null)sum += a.value;}}return sum;
}
  • 分段統計:CounterCell數組分散計數壓力
  • 偽原子性:弱一致性保證

三、實戰應用:性能調優實戰

3.1 典型場景優化

3.1.1 秒殺系統庫存管理
// 正確使用姿勢
ConcurrentHashMap<String, AtomicInteger> stockMap = new ConcurrentHashMap<>();void seckill(String itemId, int count) {stockMap.computeIfPresent(itemId, (k, v) -> {int remain = v.addAndGet(-count);if (remain < 0) {v.addAndGet(count); // 庫存回滾return v;}return v;});
}
  • 原子操作:computeIfPresent保證原子性
  • 防超賣:回滾機制保障數據一致性
3.1.2 配置中心熱加載
// 配置熱更新示例
ConcurrentHashMap<String, String> configMap = new ConcurrentHashMap<>();void loadConfig() {Map<String, String> newConfig = fetchRemoteConfig();configMap.forEach((k, v) -> {if (!newConfig.containsKey(k)) {configMap.remove(k); // 安全刪除舊配置}});newConfig.forEach(configMap::putIfAbsent);
}
  • 安全更新:forEach+putIfAbsent組合操作
  • 內存優化:弱引用+ReferenceQueue自動清理

四、性能解密:基準測試數據

4.1 多維性能對比

測試場景ConcurrentHashMapsynchronizedMap性能差異
10線程隨機讀18.2M ops/s3.1M ops/s5.8倍
100線程混合讀寫9.7M ops/s1.2M ops/s8.1倍
1000線程壓力測試2.3M ops/sOOM-

4.2 JVM參數調優指南

推薦參數配置
-XX:+UseNUMA               # 啟用NUMA內存分配
-XX:-UseBiasedLocking      # 禁用偏向鎖(高并發場景)
-XX:ResizeTLAB=true        # 自動調整TLAB大小
  • 內存優化:設置-XX:ConcGCThreads=4提升GC效率
  • 鎖優化:-XX:-ReduceInitialCardMarks減少標記開銷

五、避坑指南:常見陷阱與對策

5.1 典型錯誤案例

5.1.1 并發擴容死鎖
// 錯誤示例:擴容期間迭代操作
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<>();
new Thread(() -> map.keySet().forEach(System.out::println)).start();
// ...其他線程執行putAll觸發擴容...
  • 現象:拋出ConcurrentModificationException
  • 解決方案:使用ConcurrentHashMap.KeySetView的immutableSnapshot()
5.1.2 computeIfAbsent陷阱
// 死循環風險
map.computeIfAbsent("key", k -> {map.put("key", "value"); // 可能導致遞歸調用return "value";
});
  • 原理:compute系列方法會鎖住當前桶
  • 對策:避免在計算函數中修改同一個鍵值

結語:并發編程的未來展望

6.1 技術演進方向

  • 協程支持:Project Loom對并發集合的影響
  • 硬件級優化:利用C++20原子操作提升性能
  • 云原生適配:Kubernetes環境下的自動擴縮容策略

6.2 學習路線推薦

  1. 源碼精讀:重點研究JDK1.8的ForwardingNode實現
  2. 性能調優:使用JFR分析擴容期間的GC行為
  3. 模式擴展:實現帶TTL的ConcurrentHashMap

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/bicheng/79123.shtml
繁體地址,請注明出處:http://hk.pswp.cn/bicheng/79123.shtml
英文地址,請注明出處:http://en.pswp.cn/bicheng/79123.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

URP - 序列圖動畫的實現

效果&#xff1a; 【太妃糖耶】更新了一條視頻&#xff0c;快來圍觀&#xff01; 序列圖動畫的實現 首先先了解下序列圖樣式的紋理圖片 如上圖一可在Shader中使用該圖片制作燃燒的火的動畫&#xff0c;但是如何實現呢&#xff1f;接下來一起來看一下吧 序列圖動畫的實現原理大…

python中 str.strip() 是什么意思

在 Python 中&#xff0c;str.strip() 是字符串&#xff08;str&#xff09;類型的一個方法&#xff0c;用于移除字符串兩端的空白字符&#xff08;默認情況下&#xff09;或指定字符&#xff0c;并返回處理后的新字符串。 語法&#xff1a; str.strip([chars])chars&#xf…

記錄idea可以運行但是maven install打包卻找不到問題

解決idea使?maven多模塊install報依賴模塊的包找不到的問題 如果被依賴項?是springboot項?&#xff0c;那么可以把相關的springboot的東西移除掉&#xff0c;改造成普通項?。如果不想改造項?&#xff0c;那就添加部分的配置&#xff0c;因為springboot項?打包的時候會?…

uniapp如何獲取安卓原生的Intent對象

通過第三方app喚起&#xff0c;并且獲取第三方app喚起時攜帶的參數 因為應用a喚起應用b時&#xff0c;應用b第一時間就要拿到參數token&#xff0c;所以需要將獲取參數的方法寫在APP.vue中的onLaunch鉤子里,如果其他地方要用可以選擇vuex或者采用本地緩存。 uniapp中plus.run…

《多端統一的終極答案:X5內核增強版的渲染優化全解析》

跨端應用的需求呈爆發式增長&#xff0c;無論是電商購物、社交互動&#xff0c;還是金融理財類應用&#xff0c;都期望能夠在不同平臺上為用戶提供一致且流暢的體驗。而在這一過程中&#xff0c;跨端渲染技術成為了關鍵瓶頸。騰訊X5內核增強版的出現&#xff0c;猶如一道曙光&a…

深入理解算力:從普通電腦到宏觀計算世界

在科技飛速發展的當下&#xff0c;“算力” 一詞頻繁出現在我們的視野中&#xff0c;無論是前沿的人工智能領域&#xff0c;還是新興的區塊鏈世界&#xff0c;算力都扮演著至關重要的角色。但對于大多數普通人來說&#xff0c;算力仿佛是一個既熟悉又陌生的概念。今天&#xff…

Paramiko復用 Transport 連接解析

1. 什么是 Transport 連接&#xff1f; 在 Paramiko 中&#xff0c;Transport 是負責底層 SSH 協議通信的核心類&#xff0c;它封裝了以下功能&#xff1a; 加密通信&#xff1a;處理 SSH 協議的加密和解密。會話管理&#xff1a;維護與遠程服務器的 TCP 連接。多路復用&…

sd webui 安裝插件sd-webui-EasyPhoto依賴安裝失敗解決辦法

在最新版的SD webui中&#xff0c;可以安裝easyphoto插件&#xff0c;官方建議通過github安裝&#xff0c;對無法科學上網的用戶很不友好。對我自己來說是通過地址&#xff1a; https://gitee.com/wowai/sd-webui-EasyPhoto.git 分支&#xff1a;anyid 點擊安裝即可。 在安裝…

WEBSTORM前端 —— 第2章:CSS —— 第3節:背景屬性與顯示模式

目錄 1.Emmet寫法 2.背景屬性 &#xff08;1&#xff09; background-color &#xff08;2&#xff09; background-image &#xff08;3&#xff09; background-repeat &#xff08;4&#xff09;background-position &#xff08;5&#xff09;background-size &…

【android bluetooth 協議分析 01】【HCI 層介紹 2】【Malformed Packet 介紹】

在實際工作中遇到了 malformed packet , 我這里來分析一下。 遇到這種問題的處理思路。 1. Malformed packet 36982 2025-04-29 14:15:34.899760 controller host HCI_EVT 4 Rcvd Role Change[Malformed Packet]Frame 36982: 4 bytes on wire (32 bits), 4 bytes captured (32…

【視頻生成模型】通義萬相Wan2.1模型本地部署和LoRA微調

目錄 1 簡介2 本地部署2.1 配置環境2.2 下載模型 3 文生視頻3.1 運行命令3.2 生成結果 4 圖生視頻4.1 運行命令4.2 生成結果 5 首尾幀生成視頻5.1 運行命令5.2 生成結果 6 提示詞擴展7 LoRA微調 1 簡介 通義萬相 2.1 在 2025 年 1 月推出&#xff0c;2 月 25 日阿里巴巴宣布全…

模式識別的基本概念與理論體系

前面在討論專家系統時曾經說過&#xff0c;為了使計算機具有自動獲取知識的能力&#xff0c;除了應使它具有學習能力外&#xff0c;還應使它具有能識別諸如文字、圖形、圖象、聲音等的能力&#xff0c;計算機的這種識別能力是模式識別研究的主要內容。當然&#xff0c;模式識別…

樹的序列化 - 學習筆記

樹的序列化可以有很多種類&#xff1a;可以變成 dfs 序&#xff0c;可以變成歐拉序&#xff0c;還有什么括號序的科技。 但是除了第一個以外其他的都沒什么用&#xff08;要么也可以被已有的算法給替代掉&#xff09;。所以表面上是講樹的序列化&#xff0c;實際上還是講的 df…

KBEngine 源代碼分析(三):組網邏輯

machine 服務 machine 服務是 KBEngine 用來做服務治理的 每個節點上都需要部署 machine 服務 machine 服務使用 UDP 進行通信 服務發現的方法是其他服務使用 UDP 廣播的方式,通知所有 machine 服務 machine 服務啟動初始化 mahcine 服務初始化過程,主要做了監聽 UDP 端…

git 怎樣把本地倉庫推送到新建的遠程倉庫

將本地 Git 倉庫推送到一個新的遠程倉庫是一個常見的操作。以下是詳細的步驟&#xff1a; 步驟 1: 創建一個新的遠程倉庫 首先&#xff0c;你需要在 GitHub、GitLab 或其他代碼托管平臺上創建一個新的遠程倉庫。 例如&#xff0c;在 GitHub 上創建一個新倉庫&#xff1a; 登…

SPSS PCA+判別分析

1&#xff0c; 主成分分析PCA 我們只要對數化的變量數據&#xff1a; &#xff08;1&#xff09;對數據進行標準化處理&#xff1a; 選擇【分析】—【描述統計】—【描述】 添加要標準化的變量&#xff0c;勾選【將標準化值另存為變量(Z)】&#xff0c;再點確定 SPSS軟件本身不…

XWPFDocument生成word文檔介紹(格式 .docx)

以下是針對 XWPFDocument 的詳細解析&#xff0c;涵蓋其核心功能、常見用法及實際開發中的關鍵點&#xff1a; XWPFDocument 1. XWPFDocument 簡介2. 核心結構與類3. 核心操作詳解**3.1 段落與文本****3.2 表格操作****3.3 列表與編號****3.4 圖片插入** 4. 高級功能**4.1 頁眉…

crashpad 編譯

一環境配置 1.1設置系統UTF8編碼 1.2vs2017語言環境設置英文包 二.獲取depot_tools&#xff08;此步驟可以跳過 最新工具包已上傳下載使用即可&#xff09; windows下載壓縮包&#xff0c;然后放到系統PATH中 下載完以后&#xff0c;基本就是靠depot_tools這個工具集合了&am…

基于標注數據的情感分析模型研究

標題:基于標注數據的情感分析模型研究 內容:1.摘要 隨著互聯網的快速發展&#xff0c;大量文本數據蘊含著豐富的情感信息&#xff0c;對其進行情感分析具有重要的商業和社會價值。本研究的目的是構建基于標注數據的情感分析模型&#xff0c;以準確識別文本中的情感傾向。方法上…

【數據鏈路層深度解析】從幀結構到協議實現

目錄 一、數據鏈路層核心定位1.1 OSI模型中的位置1.2 三大核心職責 二、幀結構詳解2.1 以太網幀標準格式&#xff08;IEEE 802.3&#xff09;2.2 幀封裝代碼示例 三、核心協議機制3.1 MAC地址體系3.2 介質訪問控制CSMA/CD&#xff08;以太網沖突檢測&#xff09;現代交換機的演…