ConcurrentHashMap的演進:從Java 8之前到Java 17的實現原理深度剖析

目錄

    • 一、引言
    • 二、Java 8之前的ConcurrentHashMap
      • 1、內部結構與初始化
      • 2、Segment類
      • 3、并發控制
      • 4、擴容與重哈希
      • 5、總結
    • 三、Java 8中的ConcurrentHashMap
      • 1、數據結構
      • 2、并發控制
        • 2.1. CAS操作
        • 2.2. synchronized同步塊
      • 3、哈希計算與定位
      • 4、擴容與重哈希
      • 5、總結
    • 四、Java 17中的ConcurrentHashMap
      • 1、數據結構
      • 2、并發控制
      • 3、哈希計算與定位
      • 4、擴容與重哈希
      • 5、其他改進和優化
    • 五、總結

一、引言

在Java的并發編程中,ConcurrentHashMap以其出色的并發性能和數據一致性成為了眾多開發者的首選。從Java 5的引入至今,ConcurrentHashMap經歷了多次重大的改進和優化。本文將詳細深入全面地探討從Java 8之前到Java 17中ConcurrentHashMap的實現原理及其變化。

二、Java 8之前的ConcurrentHashMap

在Java 8之前,ConcurrentHashMap的實現原理主要基于分段鎖(Segmentation Lock)的機制,這種設計使得它能夠在高并發環境下提供良好的性能。以下是詳細的介紹:

在這里插入圖片描述

1、內部結構與初始化

ConcurrentHashMap內部主要由三個組件構成:一個Segment數組、哈希函數和鍵值對節點。其中,Segment是一個可重入的互斥鎖,每個Segment包含一個哈希表,哈希表中的每個元素都是一個鏈表。

在初始化ConcurrentHashMap時,會創建一個Segment數組,并指定初始容量和負載因子。每個Segment的初始容量和負載因子與整個ConcurrentHashMap的相同。此外,還會為每個Segment分配一個鎖,用于控制對該Segment的并發訪問。

2、Segment類

Segment類是ConcurrentHashMap實現并發控制的核心。它繼承自ReentrantLock,擁有自己的鎖,并且包含一個哈希表。Segment類中的哈希表結構與普通的HashMap類似,采用鏈表解決哈希沖突。每個鏈表節點包含一個鍵值對和一個指向下一個節點的引用。

除了哈希表之外,Segment還維護了一些統計信息,如元素數量、修改次數等。這些信息用于支持擴容和迭代器操作。

3、并發控制

當線程需要訪問ConcurrentHashMap中的某個鍵時,它會首先計算鍵的哈希值,并根據哈希值的高位定位到對應的Segment。然后,線程會嘗試獲取該Segment的鎖。如果鎖已經被其他線程持有,則當前線程會等待直到獲取鎖為止。

一旦線程獲得Segment的鎖,它就可以在該Segment內部進行哈希表的查找、插入或刪除操作。這些操作與普通的HashMap類似,但需要在鎖的保護下進行以確保線程安全。完成操作后,線程會釋放鎖,使得其他線程有機會訪問該Segment

需要注意的是,雖然每個Segment都有自己的鎖,但整個ConcurrentHashMap的并發性能并不完全取決于鎖的數量。實際上,鎖的競爭程度、哈希函數的分布性以及負載因子等因素都會對并發性能產生影響。

4、擴容與重哈希

當某個Segment的負載因子超過閾值時,會觸發擴容操作。擴容時,會創建一個新的Segment數組,并將原有Segment中的鍵值對重新散列到新的Segment數組中。這個過程涉及到大量的數據復制和重哈希計算。

為了減少擴容對并發性能的影響,ConcurrentHashMap采用了分段擴容的策略。它每次只處理一個Segment,并且在擴容過程中仍然允許其他線程訪問未處理的Segment。這樣確保了擴容操作不會阻塞整個ConcurrentHashMap的并發訪問。

此外,在擴容過程中,ConcurrentHashMap還采用了一種稱為“轉移策略”的技術來避免死鎖和饑餓問題。具體來說,當某個線程正在處理一個Segment時,如果該Segment需要擴容,那么擴容操作會由另一個線程來完成。這樣確保了處理線程不會因等待擴容而阻塞過長時間。

5、總結

Java 8之前的ConcurrentHashMap通過分段鎖的設計實現了高并發性能。它將哈希表劃分為多個段,并使用細粒度的鎖來控制對每個段的訪問。這種設計大大減少了鎖的競爭,提高了并發性能。然而,隨著Java版本的迭代和硬件性能的提升,分段鎖的設計逐漸暴露出一些問題,如內存占用較大、擴容操作復雜等。

三、Java 8中的ConcurrentHashMap

在Java 8中,ConcurrentHashMap的實現原理發生了顯著的變化,它摒棄了之前版本中的分段鎖(Segmentation Lock)機制,轉而采用了一種更為高效和靈活的并發控制策略,即CAS(Compare-and-Swap)操作結合synchronized同步塊。這種新的設計不僅簡化了數據結構,還提高了在多核處理器環境下的并發性能。

1、數據結構

Java 8中的ConcurrentHashMap底層數據結構主要由數組、鏈表和紅黑樹組成。數組用于存儲鍵值對的節點,每個節點要么是一個鏈表,要么是一個紅黑樹。當鏈表長度超過一定閾值(默認為8)時,鏈表會轉換為紅黑樹,以提高搜索效率。
在這里插入圖片描述

2、并發控制

2.1. CAS操作

CAS(Compare-and-Swap)是一種無鎖化的算法,它包含三個操作數——內存位置(V)、預期原值(A)和新值(B)。如果內存位置V的值與預期原值A相匹配,那么處理器會自動將該位置的值更新為新值B。否則,處理器不做任何操作。無論哪種情況,它都會在CAS指令之前返回該位置的值。在ConcurrentHashMap中,CAS操作被廣泛應用于節點的添加、刪除和更新等場景,以確保并發修改的安全性。

2.2. synchronized同步塊

盡管CAS操作能夠在很大程度上減少鎖的競爭,但在某些情況下,仍然需要更嚴格的同步機制來保證并發操作的正確性。因此,Java 8中的ConcurrentHashMap在必要時會使用synchronized同步塊來保護某些關鍵代碼段,如樹化操作、擴容等。與分段鎖相比,synchronized同步塊具有更低的開銷和更高的靈活性。

3、哈希計算與定位

與之前的版本類似,Java 8中的ConcurrentHashMap也使用哈希算法來計算鍵的哈希值,并根據哈希值來定位數組中的索引位置。不同的是,Java 8中的哈希計算過程更加復雜和精細,以減少哈希沖突和提高空間利用率。此外,當發生哈希沖突時,新的鍵值對會添加到鏈表或紅黑樹的末尾,而不是像之前版本那樣使用頭插法。

4、擴容與重哈希

ConcurrentHashMap中的元素數量超過數組的容量閾值時,就會觸發擴容操作。在擴容過程中,會創建一個新的數組,并將原有數組中的鍵值對重新散列到新的數組中。與之前的版本不同,Java 8中的擴容操作不再需要對整個數組進行鎖定,而是采用了更細粒度的并發控制策略。具體來說,它將數組劃分為多個小段(每個小段包含多個桶),并允許多個線程同時處理不同的小段。這樣設計可以減少鎖的競爭和提高擴容操作的并發性能。

5、總結

Java 8中的ConcurrentHashMap通過采用CAS操作結合synchronized同步塊的并發控制策略以及優化后的數據結構和哈希算法等技術手段實現了高并發性能下的線程安全訪問。與之前的版本相比,它在簡化數據結構、提高空間利用率和降低鎖競爭等方面取得了顯著的進步。這些改進使得ConcurrentHashMap成為Java并發編程中不可或缺的重要組件之一。

四、Java 17中的ConcurrentHashMap

在Java 17中,ConcurrentHashMap的實現原理基本保持了Java 8引入的設計,但可能包含了一些優化和改進,以適應新的JDK版本和硬件環境。以下是Java 17中ConcurrentHashMap實現原理的深入介紹:

1、數據結構

與Java 8相似,Java 17中的ConcurrentHashMap也使用了數組、鏈表和紅黑樹作為底層數據結構。數組用于存儲鍵值對的節點,每個節點在哈希沖突時形成鏈表,當鏈表長度超過一定閾值(默認為8)并且數組長度大于64時,鏈表會轉換為紅黑樹,以提高搜索效率。如果數組長度小于等于64,則不會進行樹化,而是采用擴容來減少哈希沖突。

2、并發控制

Java 17中的ConcurrentHashMap仍然采用CAS操作和synchronized同步塊來實現并發控制。CAS操作用于無鎖化的節點添加、刪除和更新等操作,而synchronized同步塊則用于保護樹化、擴容等需要更嚴格同步的代碼段。

不過,在Java 17中,JDK可能對這些操作進行了進一步的優化,以減少不必要的CAS操作和鎖競爭,提高并發性能。例如,通過更精細的粒度控制synchronized同步塊的范圍,或者使用更高效的鎖實現等。

3、哈希計算與定位

Java 17中的ConcurrentHashMap哈希計算過程與Java 8類似,但可能包含了一些針對新硬件環境的優化。哈希值用于定位數組中的索引位置,當發生哈希沖突時,新的鍵值對會添加到鏈表或紅黑樹的末尾。

此外,Java 17中的ConcurrentHashMap可能還引入了一些新的哈希算法或哈希沖突解決策略,以進一步減少哈希沖突和提高空間利用率。

4、擴容與重哈希

ConcurrentHashMap中的元素數量超過數組的容量閾值時,會觸發擴容操作。在Java 17中,擴容操作的基本原理與Java 8相似,即創建一個新的數組,并將原有數組中的鍵值對重新散列到新的數組中。然而,Java 17可能對擴容過程中的并發控制、數據遷移等方面進行了優化和改進。

例如,通過更細粒度的并發控制策略來減少鎖的競爭;使用更高效的數據遷移算法來減少擴容過程中的性能開銷;或者引入一些新的技術手段來提高擴容操作的并發性能和可靠性等。

5、其他改進和優化

除了上述基本原理外,Java 17中的ConcurrentHashMap還包含一些其他改進和優化:

  • 更好的內存布局和緩存利用:通過優化數據結構的內存布局和訪問模式,提高緩存利用率和減少內存訪問開銷。
  • 更高效的節點操作:通過優化節點的添加、刪除和更新等操作,減少不必要的內存分配和垃圾回收開銷。
  • 更靈活的參數配置:提供更多的參數配置選項,以便用戶根據具體應用場景進行更精細的性能調優。
  • 更完善的錯誤處理和異常處理機制:增強錯誤處理和異常處理能力,提高程序的健壯性和可靠性。

總之,在Java 17中,ConcurrentHashMap仍然是一個高性能、線程安全的并發哈希表實現,它在數據結構、并發控制、哈希計算與定位以及擴容與重哈希等方面都進行了深入的設計和優化。

五、總結

從Java 8之前到Java 17,ConcurrentHashMap經歷了顯著的演進。Java 8之前的版本采用分段鎖機制實現并發控制;Java 8引入了紅黑樹和更細粒度的鎖策略來優化性能;而Java 17在保持Java 8基本設計的同時,對并發控制和內部實現進行了進一步的優化和改進。這些變化使得ConcurrentHashMap在并發性能、內存開銷和穩定性等方面不斷得到提升和完善。作為Java并發編程中的重要組成部分,ConcurrentHashMap的演進歷程反映了Java平臺對并發性能和穩定性的持續追求和提升。在未來的Java版本中,我們可以期待更多的優化和改進,以滿足不斷增長的并發編程需求。

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

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

相關文章

廣汽埃安工廠:蔚來汽車的造車工廠有哪些?

具體來說,理想汽車目前在常州僅有一家汽車制造工廠。 一期項目于2017年12月竣工,2019年12月投產,年產能10萬輛/年。 同時,正在規劃二期工程。 產能將增至20萬輛/年。 此外,理想還計劃接管現代汽車在北京順義的第一家工…

抖音小店怎么開店注冊?別在全網找教程了,2024年最新開店教程來了

大家好,我是電商糖果 想開一家抖音小店,不會開,也不懂需要準備哪些材料。 在網上扒拉了一堆教程,不知道應該聽哪個? 害怕店鋪開錯了,后續還要關店。 有這些擔心的朋友,看到這篇文章的時候&a…

工業現場網絡性能評估方案

最近要去一個工廠排查網絡和電腦卡頓的問題,為此,我準備了以下的方案,在現場以抓包和網絡監控的方式來排查。 1.評估流程 為了評估Linux系統的網絡負荷,并使用tcpdump來捕獲數據包進行分析,您需要遵循以下幾個步驟: …

自動化搭建---環境搭建與配置

1. 確定所需環境 與項目團隊和開發人員詳細溝通,了解項目的具體環境需求。這可能包括操作系統版本、數據庫類型(如MySQL、PostgreSQL等)、Web服務器(如Apache、Nginx等)以及其他依賴軟件。 2. 安裝操作系統 根據項目…

數據倉庫與數據挖掘概述

目錄 一、數據倉庫概述 (一)從傳統數據庫到數據倉庫 (二)數據倉庫的4個特征 (三)數據倉庫系統 (四)數據倉庫系統體系結構 (五)數據倉庫數據的粒度與組織…

論文閱讀_代碼生成模型_CodeGeeX

英文名稱: CodeGeeX: A Pre-Trained Model for Code Generation with Multilingual Evaluations on HumanEval-X 中文名稱: CodeGeeX:一種用于代碼生成的預訓練模型,并在HumanEval-X上進行多語言評估 鏈接: https://arxiv.org/abs/2303.17568 代碼: http…

無處不在的智慧:嵌入式系統引領智能生活

無處不在的智慧:嵌入式系統引領智能生活 嵌入式系統作為智能生活的重要組成部分,正逐漸滲透到我們的日常生活中,引領著智能生活的發展。以下將從多個方面對嵌入式系統在智能生活中的引領作用進行詳細論述。 智能家居中的嵌入式系統應用 嵌…

訓練1 : 老頭

以前用blender做的特效 總結 頭發很費時間, 需要參考和練習眼窩周邊結構還有些待準確把握從光與影中揣摩輪廓形狀 從少量面掌握大體, 從多數面雕刻細節

terminal下環境不統一導致的程序報錯(powersell改cmd)

1.報錯現象 在terminal下利用命令行執行代碼顯示運行環境缺包: 但將命令中的參數寫入參數文件,運行train.py時,程序可以正常運行: 直接運行train.py:程序可用: 2.原因分析 參考文章 控制臺環境和項目環境不一致問…

【Mysql】InnoDB 中 B+ 樹索引的注意事項

一、根頁面萬年不動 在之前的文章里,為了方便理解,都是先畫存儲用戶記錄的葉子節點,然后再畫出存儲目錄項記錄的內節點。 但實際上 B 樹的行成過程是這樣的: 每當為某個表創建一個 B 樹索引,都會為這個索引創建一個根…

C++高級面試題:請解釋 C++ 中的標準模板庫(STL)及其常見組件

請解釋 C 中的標準模板庫(STL)及其常見組件 C 標準模板庫(Standard Template Library,STL)是 C 標準庫的一部分,提供了豐富的通用數據結構和算法實現,以及許多與數據處理相關的工具。STL 中的組…

循環隊列的實現

文章目錄 循環隊列的概念循環隊列的實現循環隊列的判空和判滿鏈表or數組 循環隊列的概念 設計你的循環隊列實現。 循環隊列是一種線性數據結構,其操作表現基于 FIFO(先進先出)原則并且隊尾被連接在隊首之后以形成一個循環。它也被稱為“環形緩…

快速下載Huggingface的大語言模型

提示:文章寫完后,目錄可以自動生成,如何生成可參考右邊的幫助文檔 文章目錄 前言一、Huggingface是什么?二、基于官方huggingface-cli下載(基礎,斷線風險)1.安裝hf下載環境2.配置環境變量3.注冊…

CSAPP-信息的表示和處理

文章目錄 概念掃盲思想理解經典好圖安全事件 概念掃盲 1.大端高位在前,小端低位在前 2.邏輯運算符(&& 、||、!)與位級運算(&、|、~)的差異 3.宏可以保證無論代碼如何編譯,都能生成…

flutterandroidx支持,【工作經驗分享】

基于Linux的pc啟動過程 我們都知道,所有的程序軟件包括操作系統都是運行在內存中的,然而我們的操作系統一般是存放在硬盤上的,當我們按下開機鍵的時候,此時內存中什么程序也沒有,因此需要借助某種方式,將操…

百度SEO工具,自動更新網站的工具

在網站SEO的過程中,不斷更新網站內容是提升排名和吸引流量的關鍵之一。而對于大多數網站管理員來說,頻繁手動更新文章并進行SEO優化可能會是一項繁瑣且耗時的任務。針對這一問題,百度自動更新文章SEO工具應運而生,它能夠幫助網站管…

搭建nginx+keepalived高可用(主備模式)

nginx安裝 1. 前置依賴安裝 yum install gcc gcc-c pcre pcre-devel zlib zlib-devel openssl openssl-devel -y2. 編譯安裝nginx nginx下載地址: https://nginx.org/en/download.html ## 安裝包位置:信息港16.11:/root/shl tar xvf nginx-1.20.2.ta…

chartjs 餅狀圖

之前要把canvas先清除掉&#xff0c;不然刷新數據&#xff0c;還會有前面的圖表 function clearCanvas(){$(#donutChart).remove();$(#chartdiv).append(<canvas id"donutChart" style"min-height: 500px; height: 500px; max-height: 500px; max-width: 70%…

淺談mysql mvcc

目錄 前言 mvcc 是如何工作的&#xff1f; 數據的更新 前言 mvcc 與一個事物的隔離級別有關&#xff0c;未提交讀永遠讀的是當前值&#xff0c;串行化是通過加鎖實現&#xff0c;這兩種隔離級別都與mvcc 沒有任何關系。只要一提到mvcc應該想到的是讀提交以及可重復讀&#…

vue+element ui上傳圖片到七牛云服務器

本來打算做一個全部都是前端完成的資源上傳到七牛云的demo&#xff0c;但是需要獲取token&#xff0c;經歷了九九八十一難&#xff0c;最終還是選擇放棄&#xff0c;token從后端獲取&#xff08;springboot&#xff09;。如果你們有前端直接能解決的麻煩記得私我哦&#xff01;…