java8 ConcurrentHashMap 桶級別鎖實現機制

Java 8 ConcurrentHashMap 桶級別鎖實現機制

Java 8 中的 ConcurrentHashMap 拋棄了分段鎖設計,采用了更細粒度的桶級別鎖(bucket-level locking)實現,這是其并發性能提升的關鍵。下面詳細解析其實現原理:

1. 基本實現原理

桶級別鎖的核心思想是:只鎖定當前操作的哈希桶(鏈表或樹的頭節點),而不是整個表或某個段。

關鍵實現方式:

  • CAS + synchronized 組合控制
  • 鎖對象是每個桶的頭節點
  • 讀操作完全無鎖(volatile讀)
  • 寫操作僅在必要時加鎖

2. 具體實現細節

2.1 鎖獲取方式

// putVal方法中的鎖獲取片段
synchronized (f) { // f是桶的頭節點if (tabAt(tab, i) == f) { // 雙重檢查// 執行插入操作...}
}

2.2 鎖的獲取條件

  1. 桶不為空時才會加鎖
  2. 只鎖住當前桶的頭節點
  3. 通過 synchronized 關鍵字實現(JVM優化后的偏向鎖/輕量級鎖)

3. 實現步驟分解

3.1 插入元素時的鎖控制流程

  1. 計算 key 的哈希并定位桶位置
  2. 如果桶為空,使用 CAS 無鎖插入
    if (casTabAt(tab, i, null, new Node<K,V>(hash, key, value, null)))break;
    
  3. 如果桶不為空,則鎖住頭節點:
    synchronized (f) {// 處理鏈表或樹
    }
    

3.2 鎖的細粒度驗證

synchronized (f) {if (tabAt(tab, i) == f) { // 再次確認當前節點仍是頭節點// 實際處理邏輯}
}

這種雙重檢查確保:

  • 防止在獲取鎖期間桶已被其他線程修改
  • 保證操作的原子性

4. 技術優勢

  1. 更高的并發度

    • 理論上并發度 = 哈希桶數量(默認16 → 可能成千上萬)
  2. 更低的鎖競爭

    • 不同桶的操作完全并行
    • 只有哈希沖突時才會競爭
  3. 自適應鎖優化

    • JVM 會根據競爭情況自動升級鎖(偏向鎖→輕量級鎖→重量級鎖)
  4. 與擴容協同

    • 擴容時通過 ForwardingNode 保證操作可以繼續

5. 與 Java 7 分段鎖對比

特性Java 7 分段鎖Java 8 桶級別鎖
鎖粒度段(默認16)單個桶
鎖實現ReentrantLocksynchronized
讀操作需要段鎖完全無鎖
擴容段獨立擴容整體協同擴容
沖突處理鏈表鏈表+紅黑樹

6. 實際代碼示例

6.1 鏈表情況下的鎖應用

// putVal方法片段
synchronized (f) {if (tabAt(tab, i) == f) {if (fh >= 0) { // 普通鏈表節點binCount = 1;for (Node<K,V> e = f;; ++binCount) {// 遍歷鏈表...if ((e = e.next) == null) {e.next = new Node<K,V>(hash, key, value, null);break;}}}}
}

6.2 樹情況下的鎖應用

else if (f instanceof TreeBin) {Node<K,V> p;binCount = 2;if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key, value)) != null) {oldVal = p.val;if (!onlyIfAbsent)p.val = value;}
}

7. 關鍵設計考量

  1. synchronized 優化

    • Java 6 后 synchronized 性能已大幅提升
    • JVM 會根據競爭情況自動優化
  2. CAS 失敗回退

    • 當 CAS 插入失敗(競爭)時才使用鎖
  3. 死鎖避免

    • 只按固定順序獲取單個鎖
    • 不會出現交叉鎖請求
  4. 內存可見性

    • 通過 volatile 變量保證
    • setTabAt/tabAt 使用 Unsafe 保證原子性

這種桶級別鎖設計使得 ConcurrentHashMap 在 Java 8 中實現了:

  • 更高的并發吞吐量
  • 更低的操作延遲
  • 更平滑的性能曲線
  • 更好的可擴展性

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

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

相關文章

Python正則表達式實戰指南

一 正則表達式庫正則表達式是文本處理中不可或缺的強大工具&#xff0c;Python通過re模塊提供了完整的正則表達式支持。本文將詳細介紹re模塊中最常用的match()、search()和findall()函數&#xff0c;以及貪婪模式與非貪婪模式的區別&#xff0c;幫助讀者掌握Python中正則表達式…

使用球體模型模擬相機成像:地面與天空的可見性判斷與紋理映射

在傳統相機模擬中&#xff0c;地面通常被建模為一個平面&#xff08;Plane&#xff09;&#xff0c;這在低空場景下是合理的。但在更大視場范圍或遠距觀察時&#xff0c;地球的曲率不可忽視。因此&#xff0c;我們需要將地面模型從平面升級為球體&#xff0c;并基于球面與光線的…

Agent自動化與代碼智能

核心問題&#xff1a; 現在很多團隊做AI系統有個大毛病&#xff1a;只顧追求“高大上”的新技術&#xff08;尤其是AI Agent&#xff09;&#xff0c;不管實際業務需不需要。 結果系統搞得又貴、又復雜、還容易出錯。大家被“Agent”這個概念搞暈了&#xff1a;到底啥時候用簡單…

SQL141 試卷完成數同比2020年的增長率及排名變化

SQL141 試卷完成數同比2020年的增長率及排名變化 withtemp as (selectexam_id,tag,date(submit_time) as submit_timefromexamination_infoleft join exam_record using (exam_id)wheresubmit_time is not null),2021_temp as (selecttag,count(*) as exam_cnt_21,rank() over…

C語言<數據結構-單鏈表>

鏈表是一種常見且重要的數據結構&#xff0c;在 C 語言中&#xff0c;它通過指針將一系列的節點連接起來&#xff0c;每個節點可以存儲不同類型的數據。相比數組&#xff0c;鏈表在插入和刪除元素時不需要移動大量數據&#xff0c;具有更好的靈活性&#xff0c;尤其適合處理動態…

archive/tar: unknown file mode ?rwxr-xr-x

這個是我在docker build報錯的&#xff0c;這是一個node.js項目。我猜你也是一個node.js下的項目&#xff0c;或者前端項目。 解決方法&#xff1a; .dockerignore里面寫一下node_modules就行了。 未能解決&#xff1a;archive/tar&#xff1a;未知文件模式&#xff1f;rwxr-…

【前端】ikun-markdown: 純js實現markdown到富文本html的轉換庫

文章目錄背景界面當前支持的 Markdown 語法不支持的Markdown 語法代碼節選背景 出于興趣,我使用js實現了一個 markdown語法 -> ast語法樹 -> html富文本的庫, 其速度應當慢于正則實現的同類js庫, 但是語法擴展性更好, 嵌套列表處理起來更方便. 界面 基于此js實現vue組…

【echarts踩坑記錄】為什么第二個Y軸最大值不整潔

目錄問題復現示意圖&#xff1a;解決方法有以下幾種&#xff1a;1. 在y軸配置中手動設置max屬性&#xff1a;2. 使用ECharts提供的坐標軸標簽格式化功能&#xff1a;&#x1f680;寫在最后問題復現示意圖&#xff1a; 今天在用echarts圖表的時候&#xff0c;出現了一個小問題。…

Duplicate cleaner pro 的使用技巧

Duplicate cleaner pro 的使用技巧前言文件去重基本介紹經驗之談目錄結構修改盤符起因方法手動分配方法?數據修改方法安裝sqlite-web修改數據庫GPU加速安裝驅動獲取驅動和硬件信息安裝CUDA配置環境變量&#xff08;如果是自定義安裝&#xff09;創建程序<1>獲取參數和命…

數字孿生技術引領UI前端設計新趨勢:增強現實與虛擬現實的融合應用

hello寶子們...我們是艾斯視覺擅長ui設計和前端數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;AR 與 VR 的 “割裂” 與數字孿生的 “融合” 契機增強現實&#xff08;AR&…

Qt使用dump文件記錄并查找軟件奔潰信息詳細教程

Qt使用dump文件記錄并查找軟件奔潰信息一、dump文件概述1、dump文件的基本概念2、dump文件的常見類型3、dump文件的分析工具4、dump文件的應用場景二、具體實現步驟1、下載dbghelp庫2、將庫添加到自己的工程中3、main.cpp添加代碼記錄奔潰日志4、編寫測試代碼5、測試6、結果查看…

UI前端與數字孿生結合案例分享:智慧城市的智慧能源管理系統

hello寶子們...我們是艾斯視覺擅長ui設計、前端開發、數字孿生、大數據、三維建模、三維動畫10年經驗!希望我的分享能幫助到您!如需幫助可以評論關注私信我們一起探討!致敬感謝感恩!一、引言&#xff1a;能源管理的 “數字孿生革命”智慧城市的能源系統正面臨 “供需失衡、損耗…

Android 16系統源碼_SplashScreen窗口的創建流程(一)

一 點擊桌面圖標觸發SplashScreen 1.1 點擊桌面圖標打開應用 點擊桌面的短信圖標&#xff0c;然后打開短信頁面&#xff0c;使用winscope獲取數據。從點擊短信圖標到應用內容完全展開&#xff0c;中間有出現一個標題帶有“Splash Screen”字符串的窗口。 二 Splash Screen窗口創…

線性代數學習筆記

矩陣 矩陣是一種非常重要的數學對象,它通常由一個由數字排成的矩形陣列來定義。一個矩陣由若干行和若干列組成,被稱為矩陣的行數和列數。一般情況下,矩陣的行數和列數分別用 n n n 和 m m m 表示。<

2025.7.13總結

每次寫日記&#xff0c;總覺得自我感受不是很好&#xff0c;腦子總會有許多消極思想。在網上&#xff0c;我曾看到一個關于“人生是一場巨大的事與愿違”&#xff0c;可能&#xff0c;真的是這個樣子吧。以前的我&#xff0c;有上進心&#xff0c;有目標感&#xff0c;腳踏實地…

linux-網絡-網絡管理發展歷程

Linux 的網絡管理機制經歷了多個階段的發展&#xff0c;從早期的靜態配置到現代動態管理工具的出現&#xff0c;反映了 Linux 系統在網絡連接、自動化和用戶體驗方面的不斷演進。以下是 Linux 網絡管理發展的主要階段&#xff1a;1. 早期的靜態網絡配置&#xff08;傳統方式&am…

華為 GaussDB :技術特性、應用局限與市場爭議

3-5月間&#xff0c;老夫在某學校帶了這門課&#xff0c;簡單總結一下課程外的看法&#xff1a;華為 GaussDB 作為華為云生態中的核心數據庫產品&#xff0c;自推出以來便承載著華為在數據基礎設施領域的戰略野心。其技術路線既延續了開源數據庫的兼容性優勢&#xff0c;又深度…

從零開始學習深度學習—水果分類之PyQt5App

一、項目背景?&#xff1a;本項目是“從零開始學習深度學習”系列中的第二個實戰項目&#xff0c;旨在實現第一個簡易App(圖像分類任務——水果分類)&#xff0c;進一步地落地AI模型應用&#xff0c;幫助初學者初步了解模型落地。基于PyQt5圖形界面的水果圖像分類系統&#xf…

小架構step系列13:測試用例的加載

1 概述測試用例的編寫要有一些基礎的規范&#xff0c;在本文先定義文件名稱和測試用例方法名的規范。2 文件加載原理先從源碼來看一下測試用例的文件加載原理。2.1 文件的匹配主要是通過注解來掃描測試用例。// 在IDEA測試用例啟動時&#xff0c;調用junit-platform-launcher-x…

K8S的CNI之calico插件升級至3.30.2

前言宿主機ping不通K8S的pod&#xff0c;一直存在丟包的現象&#xff0c;排查了防火墻、日志、詳細信息等沒發現什么問題&#xff0c;最后搜索發現&#xff0c;是因為把K8S的版本升級之后&#xff0c;舊版本的CNI插件不適配原因導致的&#xff0c;于是就把calico也一并升級并且…