自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

高并發(fā)神器!ConcurrentHashMap為何如此高效?

開(kāi)發(fā) 開(kāi)發(fā)工具
ConcurrentHashMap作為Java中一個(gè)重要的并發(fā)集合類(lèi),憑借其分段鎖和CAS機(jī)制,在保證線程安全的同時(shí),大大提升了性能。JDK 1.7中通過(guò)Segment的分段鎖來(lái)降低鎖競(jìng)爭(zhēng),而JDK 1.8中則進(jìn)一步改進(jìn)為無(wú)鎖化操作和紅黑樹(shù)的結(jié)構(gòu),大幅度提升了性能和并發(fā)性。

引言

大家好,我是小米!今天我們來(lái)聊聊Java中一個(gè)超級(jí)實(shí)用的線程安全集合類(lèi)——ConcurrentHashMap。對(duì)于多線程環(huán)境中需要頻繁讀寫(xiě)數(shù)據(jù)的場(chǎng)景來(lái)說(shuō),ConcurrentHashMap無(wú)疑是個(gè)好幫手。那么,為什么ConcurrentHashMap效率高?底層實(shí)現(xiàn)的奧秘又是什么?接下來(lái),讓我們一探究竟。

圖片圖片

ConcurrentHashMap與Hashtable的對(duì)比

在多線程環(huán)境中,我們常常需要保證數(shù)據(jù)的線程安全性。說(shuō)到實(shí)現(xiàn)線程安全,ConcurrentHashMap和Hashtable都是不錯(cuò)的選擇,但二者的性能表現(xiàn)卻有很大差異。

Hashtable:同步鎖的性能瓶頸

Hashtable作為Java早期的線程安全類(lèi),主要通過(guò)Synchronized關(guān)鍵字進(jìn)行方法級(jí)別的同步來(lái)保證線程安全。比如,在執(zhí)行put或get操作時(shí),Hashtable會(huì)鎖住整個(gè)對(duì)象,導(dǎo)致同一時(shí)間只能有一個(gè)線程訪問(wèn)或修改數(shù)據(jù)。這樣雖然保證了安全性,但性能相對(duì)低下。

ConcurrentHashMap:分段鎖的高效設(shè)計(jì)

ConcurrentHashMap的核心思想是分段鎖,這使得它在性能上要遠(yuǎn)優(yōu)于Hashtable。簡(jiǎn)單來(lái)說(shuō),ConcurrentHashMap將數(shù)據(jù)劃分成多個(gè)段(Segment),每個(gè)Segment對(duì)應(yīng)一個(gè)鎖。不同線程訪問(wèn)不同Segment的數(shù)據(jù)時(shí),可以同時(shí)進(jìn)行而不互相阻塞,從而提高了并發(fā)性能。

Java的兩個(gè)主要版本(1.7和1.8)對(duì)ConcurrentHashMap的底層結(jié)構(gòu)有很大的差別,我們一起來(lái)看看它們的演變過(guò)程。

JDK 1.7:Segment分段鎖

在JDK 1.7中,ConcurrentHashMap使用了分段鎖(Segment)的設(shè)計(jì)。通過(guò)這一設(shè)計(jì),ConcurrentHashMap達(dá)到了提高并發(fā)訪問(wèn)率的效果。

底層結(jié)構(gòu):Segment數(shù)組 + HashEntry鏈表

ConcurrentHashMap在底層將數(shù)據(jù)分為多個(gè)Segment,每個(gè)Segment內(nèi)部由鏈表存儲(chǔ)數(shù)據(jù)。這樣一來(lái),ConcurrentHashMap將整個(gè)Map分成了若干個(gè)小的子Map,每個(gè)Segment相當(dāng)于一個(gè)小的Hashtable,持有一個(gè)獨(dú)立的鎖。因此,多個(gè)線程訪問(wèn)不同Segment的元素時(shí)不會(huì)相互影響,從而提高了并發(fā)性能。

如何實(shí)現(xiàn)分段鎖?

ConcurrentHashMap中會(huì)對(duì)每一個(gè)鍵值對(duì)進(jìn)行哈希計(jì)算,以確定它屬于哪個(gè)Segment。每個(gè)Segment鎖住一個(gè)區(qū)域的數(shù)據(jù),這樣每次只鎖定一個(gè)Segment,即使一個(gè)Segment被鎖定,其他Segment也可以同時(shí)被訪問(wèn),這就避免了整個(gè)Map鎖住的低效情況。

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):提高了并發(fā)性能,多個(gè)線程可以同時(shí)操作不同的Segment。
  • 缺點(diǎn):Segment數(shù)量(默認(rèn)16個(gè))固定后,無(wú)法動(dòng)態(tài)擴(kuò)容。即使并發(fā)再高,也無(wú)法突破這個(gè)限制。

JDK 1.8:無(wú)Segment,鏈表+紅黑樹(shù)+CAS

JDK 1.8中,ConcurrentHashMap的底層結(jié)構(gòu)和實(shí)現(xiàn)方式發(fā)生了重大變化,Segment不再存在,取而代之的是更為精簡(jiǎn)的實(shí)現(xiàn)方式。JDK 1.8摒棄了Segment鎖機(jī)制,而是采用了數(shù)組+鏈表+紅黑樹(shù)的組合數(shù)據(jù)結(jié)構(gòu)。

數(shù)據(jù)結(jié)構(gòu):Node數(shù)組 + 鏈表/紅黑樹(shù)

JDK 1.8的ConcurrentHashMap與1.8版本的HashMap非常相似,底層通過(guò)一個(gè)Node數(shù)組來(lái)存儲(chǔ)數(shù)據(jù)。如果某個(gè)桶中有大量hash沖突的數(shù)據(jù),會(huì)先形成鏈表;當(dāng)鏈表長(zhǎng)度超過(guò)一定閾值(8)后,會(huì)轉(zhuǎn)化成紅黑樹(shù)結(jié)構(gòu),從而提高查詢效率。

并發(fā)控制:CAS + synchronized

ConcurrentHashMap 1.8 的線程安全主要通過(guò)CAS(Compare And Swap)和synchronized關(guān)鍵字來(lái)實(shí)現(xiàn),而不是之前的鎖住整個(gè)Segment。這樣在進(jìn)行增刪改查時(shí),只需要鎖住當(dāng)前操作的鏈表頭部節(jié)點(diǎn)即可,大大降低了鎖的粒度,進(jìn)一步提升了并發(fā)效率。

  • CAS機(jī)制:CAS在檢測(cè)到變量未被其他線程修改時(shí),直接更新變量的值。相比傳統(tǒng)的鎖機(jī)制,CAS可以在無(wú)鎖的情況下完成并發(fā)更新,大大提高了效率。
  • synchronized:當(dāng)CAS無(wú)法保證安全性時(shí),才會(huì)退而采用synchronized進(jìn)行保護(hù)。JDK 1.8通過(guò)這種靈活的設(shè)計(jì),進(jìn)一步提升了并發(fā)性能。

優(yōu)缺點(diǎn)

  • 優(yōu)點(diǎn):性能較JDK 1.7更優(yōu),不再依賴(lài)Segment;鎖的粒度進(jìn)一步縮小。
  • 缺點(diǎn):實(shí)現(xiàn)較復(fù)雜,對(duì)內(nèi)存占用和系統(tǒng)資源提出了更高的要求。

ConcurrentHashMap的核心機(jī)制剖析

1. get操作

get操作在ConcurrentHashMap中是無(wú)鎖的,主要通過(guò)定位到具體的Node節(jié)點(diǎn)來(lái)直接獲取數(shù)據(jù)。

流程:

  1. 首先通過(guò)hash值確定數(shù)據(jù)的位置。
  2. 若找到的桶是鏈表,則遍歷鏈表尋找對(duì)應(yīng)的節(jié)點(diǎn)。
  3. 若桶內(nèi)為紅黑樹(shù),則使用樹(shù)的查找邏輯獲取目標(biāo)節(jié)點(diǎn)。

2. put操作

在執(zhí)行put時(shí),ConcurrentHashMap會(huì)嘗試使用CAS來(lái)添加元素。如果當(dāng)前節(jié)點(diǎn)位置為空,CAS更新會(huì)成功;否則,系統(tǒng)會(huì)退而使用synchronized鎖住節(jié)點(diǎn)進(jìn)行更新操作。

流程:

  • 計(jì)算key的hash值,定位到具體的桶。
  • 若該位置為空,則使用CAS將新值插入。
  • 若該位置已存在數(shù)據(jù):

若為鏈表,遍歷鏈表并添加至末尾;鏈表長(zhǎng)度超過(guò)8則轉(zhuǎn)化為紅黑樹(shù)。

若為紅黑樹(shù),則按照紅黑樹(shù)的插入規(guī)則進(jìn)行更新。

  • 如果容量超過(guò)閾值,則觸發(fā)擴(kuò)容。

3. 擴(kuò)容機(jī)制

與HashMap類(lèi)似,ConcurrentHashMap在容量不足時(shí)會(huì)進(jìn)行擴(kuò)容。不同的是,ConcurrentHashMap的擴(kuò)容操作是分段進(jìn)行的。

  • 分段擴(kuò)容:在擴(kuò)容過(guò)程中,多個(gè)線程可以協(xié)作進(jìn)行桶數(shù)據(jù)遷移,而不是一個(gè)線程獨(dú)自完成擴(kuò)容,從而減少了線程阻塞。

ConcurrentHashMap的優(yōu)勢(shì)總結(jié)

  • 高并發(fā)性能:JDK 1.8后的ConcurrentHashMap通過(guò)CAS操作和synchronized,避免了全面鎖的低效問(wèn)題,鎖的粒度更小,提高了整體并發(fā)性。
  • 高效數(shù)據(jù)結(jié)構(gòu):引入紅黑樹(shù),提升了查詢效率,使得沖突嚴(yán)重的情況下,依然能保持較高的訪問(wèn)效率。
  • 分段擴(kuò)容:擴(kuò)容過(guò)程可由多個(gè)線程協(xié)作進(jìn)行,進(jìn)一步提升了多線程環(huán)境下的性能表現(xiàn)。

END

ConcurrentHashMap作為Java中一個(gè)重要的并發(fā)集合類(lèi),憑借其分段鎖和CAS機(jī)制,在保證線程安全的同時(shí),大大提升了性能。JDK 1.7中通過(guò)Segment的分段鎖來(lái)降低鎖競(jìng)爭(zhēng),而JDK 1.8中則進(jìn)一步改進(jìn)為無(wú)鎖化操作和紅黑樹(shù)的結(jié)構(gòu),大幅度提升了性能和并發(fā)性。

在實(shí)際開(kāi)發(fā)中,如果你需要一個(gè)線程安全、高并發(fā)的Map集合,ConcurrentHashMap絕對(duì)是一個(gè)值得信賴(lài)的選擇!希望今天的分享能夠幫助大家更好地理解ConcurrentHashMap的底層設(shè)計(jì)及其優(yōu)點(diǎn),咱們下次再一起探討更多Java黑科技!

責(zé)任編輯:武曉燕 來(lái)源: 軟件求生
相關(guān)推薦

2024-02-26 00:00:00

JavaScript單線程高效

2009-04-14 19:30:08

虛擬化VmwareIT

2009-12-04 09:46:02

Linux操作系統(tǒng)

2015-01-08 15:38:34

Fire Phone

2021-01-26 16:21:46

邊緣計(jì)算5GIoT

2024-09-18 05:30:00

GPU內(nèi)存人工智能

2014-08-08 15:36:58

2021-08-25 23:08:52

微服務(wù)編程IT

2022-05-06 17:34:27

安全代碼軟件漏洞

2024-03-22 11:27:54

電纜管理數(shù)據(jù)中心

2022-06-08 13:11:35

比特幣挖礦區(qū)塊鏈

2010-07-16 16:06:11

求職

2009-09-17 13:06:24

2012-05-10 10:23:10

技術(shù)人員開(kāi)發(fā)

2013-07-16 09:31:11

2012-04-24 14:41:15

HTML5

2021-08-30 14:23:41

身份驗(yàn)證隱私管理網(wǎng)絡(luò)安全

2025-01-13 07:33:47

2017-10-25 14:28:27

Java工程師火爆原因

2013-04-27 10:31:56

大數(shù)據(jù)全球技術(shù)峰會(huì)Hadoop
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)