ConcurrentHashMap

背景

線程不安全的HashMap

因為多線程環(huán)境下撼唾,使用Hashmap進行put操作會引起死循環(huán)壕翩,導(dǎo)致CPU利用率接近100%,所以在并發(fā)情況下不能使用HashMap稠诲。

效率低下的HashTable容器

HashTable容器使用synchronized來保證線程安全捎泻,但在線程競爭激烈的情況下HashTable的效率非常低下飒炎。
因為當(dāng)一個線程訪問HashTable的同步方法時,其他線程訪問HashTable的同步方法時笆豁,可能會進入阻塞或輪詢狀態(tài)郎汪。如線程1使用put進行添加元素定欧,線程2不但不能使用put方法添加元素,并且也不能使用get方法來獲取元素怒竿,所以競爭越激烈效率越低。

鎖分段技術(shù)

ConcurrentHashMap所使用的鎖分段技術(shù)扩氢,首先將數(shù)據(jù)分成一段一段的存儲耕驰,然后給每一段數(shù)據(jù)配一把鎖,當(dāng)一個線程占用鎖訪問其中一個段數(shù)據(jù)的時候录豺,其他段的數(shù)據(jù)也能被其他線程訪問朦肘。
有些方法需要跨段,比如size()和containsValue()双饥,它們可能需要鎖定整個表而而不僅僅是某個段媒抠,這需要按順序鎖定所有段,操作完畢后咏花,又按順序釋放所有段的鎖趴生。
這里“按順序”是很重要的,否則極有可能出現(xiàn)死鎖昏翰,在ConcurrentHashMap內(nèi)部苍匆,段數(shù)組是final的,并且其成員變量實際上也是final的棚菊,但是浸踩,僅僅是將數(shù)組聲明為final的并不保證數(shù)組成員也是final的,這需要實現(xiàn)上的保證统求。這可以確保不會出現(xiàn)死鎖检碗,因為獲得鎖的順序是固定的。

image.png

ConcurrentHashMap是由Segment數(shù)組結(jié)構(gòu)和HashEntry數(shù)組結(jié)構(gòu)組成码邻。Segment是一種可重入鎖ReentrantLock折剃,在ConcurrentHashMap里扮演鎖的角色,HashEntry則用于存儲鍵值對數(shù)據(jù)像屋。
一個ConcurrentHashMap里包含一個Segment數(shù)組微驶,Segment的結(jié)構(gòu)和HashMap類似,是一種數(shù)組和鏈表結(jié)構(gòu)开睡, 一個Segment里包含一個HashEntry數(shù)組因苹,每個HashEntry是一個鏈表結(jié)構(gòu)的元素, 每個Segment守護者一個HashEntry數(shù)組里的元素,當(dāng)對HashEntry數(shù)組的數(shù)據(jù)進行修改時篇恒,必須首先獲得它對應(yīng)的Segment鎖扶檐。

應(yīng)用場景

當(dāng)有一個大數(shù)組時需要在多個線程共享時就可以考慮是否把它給分層多個節(jié)點了,避免大鎖胁艰。并可以考慮通過hash算法進行一些模塊定位款筑。

解讀

不變和易變

ConcurrentHashMap完全允許多個讀操作并發(fā)進行智蝠,讀操作并不需要加鎖。如果使用傳統(tǒng)的技術(shù)奈梳,如HashMap中的實現(xiàn)杈湾,如果允許可以在hash鏈的中間添加或刪除元素,讀操作不加鎖將得到不一致的數(shù)據(jù)攘须。
ConcurrentHashMap實現(xiàn)技術(shù)是保證HashEntry幾乎是不可變的漆撞。


image.png

可以看到除了value不是final的,其它值都是final的于宙,這意味著不能從hash鏈的中間或尾部添加或刪除節(jié)點浮驳,因為這需要修改next 引用值,所有的節(jié)點的修改只能從頭部開始捞魁。對于put操作至会,可以一律添加到Hash鏈的頭部。
但是對于remove操作谱俭,可能需要從中間刪除一個節(jié)點奉件,這就需要將要刪除節(jié)點的前面所有節(jié)點整個復(fù)制一遍,最后一個節(jié)點指向要刪除結(jié)點的下一個結(jié)點昆著。這在講解刪除操作時還會詳述瓶蚂。為了確保讀操作能夠看到最新的值,將value設(shè)置成volatile宣吱,這避免了加鎖窃这。

數(shù)據(jù)結(jié)構(gòu)

Hash表的一個很重要方面就是如何解決hash沖突,ConcurrentHashMap 和HashMap使用相同的方式征候,都是將hash值相同的節(jié)點放在一個hash鏈中杭攻。與HashMap不同的是,ConcurrentHashMap使用多個子Hash表疤坝,也就是段(Segment)兆解。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市跑揉,隨后出現(xiàn)的幾起案子锅睛,更是在濱河造成了極大的恐慌,老刑警劉巖历谍,帶你破解...
    沈念sama閱讀 221,430評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件现拒,死亡現(xiàn)場離奇詭異,居然都是意外死亡望侈,警方通過查閱死者的電腦和手機印蔬,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,406評論 3 398
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來脱衙,“玉大人侥猬,你說我怎么就攤上這事例驹。” “怎么了退唠?”我有些...
    開封第一講書人閱讀 167,834評論 0 360
  • 文/不壞的土叔 我叫張陵鹃锈,是天一觀的道長。 經(jīng)常有香客問我瞧预,道長屎债,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 59,543評論 1 296
  • 正文 為了忘掉前任松蒜,我火速辦了婚禮,結(jié)果婚禮上已旧,老公的妹妹穿的比我還像新娘秸苗。我一直安慰自己,他們只是感情好运褪,可當(dāng)我...
    茶點故事閱讀 68,547評論 6 397
  • 文/花漫 我一把揭開白布惊楼。 她就那樣靜靜地躺著,像睡著了一般秸讹。 火紅的嫁衣襯著肌膚如雪檀咙。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,196評論 1 308
  • 那天璃诀,我揣著相機與錄音弧可,去河邊找鬼。 笑死劣欢,一個胖子當(dāng)著我的面吹牛棕诵,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凿将,決...
    沈念sama閱讀 40,776評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼校套,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了牧抵?” 一聲冷哼從身側(cè)響起笛匙,我...
    開封第一講書人閱讀 39,671評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎犀变,沒想到半個月后妹孙,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,221評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡获枝,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,303評論 3 340
  • 正文 我和宋清朗相戀三年涕蜂,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片映琳。...
    茶點故事閱讀 40,444評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡机隙,死狀恐怖蜘拉,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情有鹿,我是刑警寧澤旭旭,帶...
    沈念sama閱讀 36,134評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站葱跋,受9級特大地震影響持寄,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜娱俺,卻給世界環(huán)境...
    茶點故事閱讀 41,810評論 3 333
  • 文/蒙蒙 一稍味、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧荠卷,春花似錦模庐、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,285評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至慎冤,卻和暖如春疼燥,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蚁堤。 一陣腳步聲響...
    開封第一講書人閱讀 33,399評論 1 272
  • 我被黑心中介騙來泰國打工醉者, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人披诗。 一個月前我還...
    沈念sama閱讀 48,837評論 3 376
  • 正文 我出身青樓湃交,卻偏偏與公主長得像,于是被迫代替她去往敵國和親藤巢。 傳聞我的和親對象是個殘疾皇子搞莺,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,455評論 2 359

推薦閱讀更多精彩內(nèi)容