Java面試需知--ConcurrentHashMap源碼分析

ConcurrentHashMap 是做Java開發(fā)必須要掌握的類的用法之一豫尽,它彌補(bǔ)了HashTable在并發(fā)環(huán)境下的性能的不足钢猛。引用分離鎖的概念,極大地增強(qiáng)了并發(fā)性能。

ConcurrentHashMap 存儲(chǔ)結(jié)構(gòu)圖

圖1-1 存儲(chǔ)結(jié)構(gòu)

ConcurrentHashMap相比于HashMap新增了一個(gè)segments數(shù)組酒繁,每一個(gè)數(shù)組分別對(duì)應(yīng)一把鎖,ConcurrentHashMap默認(rèn)情況下這個(gè)數(shù)組長度為16控妻,即在理想狀態(tài)下ConcurrentHashMap可以支持16個(gè)線程無鎖安全訪問數(shù)據(jù)欲逃。

舉個(gè)例子:當(dāng)有一個(gè)線程正在修改segments[0]中的內(nèi)容時(shí),同時(shí)另一個(gè)線程要查詢的value剛好在segment[2]中饼暑,那么segment[2]就不會(huì)加鎖稳析。

ConcurrentHashMap中的HashEntry內(nèi)部類

static final class HashEntry<K,V> {    
  final K key;    
  final int hash;    
  volatile V value;    
  final HashEntry<K,V> next; 
...
}

HashMap是以數(shù)組加鏈表的形式存儲(chǔ)數(shù)據(jù)的,ConcurrentHashMap當(dāng)然也不例外弓叛,上面這個(gè)是ConcurrentHashMap中用作鏈表存儲(chǔ)的內(nèi)部類彰居。它除了value 其余變量全部設(shè)為final型。

ConcurrentHashMap 中的數(shù)據(jù)交互

其實(shí)分析ConcurrentHashMap最重要的就是分析它是怎么做數(shù)據(jù)交互的撰筷,下面將會(huì)依次分析ConcurrentHashMap中數(shù)據(jù)是怎么存儲(chǔ)和刪除

1.如何put

由于HashEntry 中 next變量被聲明為了final陈惰,那么要增加一個(gè)新的Entry那就只能從頭部添加,如下圖:

圖1-2 put

它會(huì)將新new出來的HashEntry指向原本數(shù)組指向的表頭元素毕籽,然后將數(shù)組指向這個(gè)類抬闯。

2.如何delete

ConcurrentHashMap中刪除一個(gè)元素可不像傳統(tǒng)鏈表刪除一個(gè)元素時(shí)只需要修改下指針位置那么簡單。因?yàn)?code>HashEntry中next為final類型关筒,所以位于要?jiǎng)h除的元素之前的元素必須要重新new一次溶握,再依次指定next。如下圖:

圖1-3 delete

ConcurrentHashMap 中的數(shù)據(jù)臟讀

參照?qǐng)D1-3蒸播,我們假設(shè)一種情況睡榆,當(dāng)線程1想要讀取e3的數(shù)據(jù)萍肆,此時(shí)讀取到了e1位置;而與此同時(shí)線程2正在執(zhí)行刪除e3操作胀屿,那么就有可能線程2執(zhí)行完刪除操作后塘揣,線程1仍然能讀取出e3的數(shù)據(jù)。這就是ConcurrentHashMap中的數(shù)據(jù)臟讀宿崭,所以ConcurrentHashMap不適合存儲(chǔ)敏感類型的數(shù)據(jù)亲铡。

必須應(yīng)該了解的Clear方法

首先看一下ConcurrentHashMap中的clear方法的源碼

   public void clear() {
        final Segment<K,V>[] segments = this.segments;
        for (int j = 0; j < segments.length; ++j) {
            Segment<K,V> s = segmentAt(segments, j);
            if (s != null)
                s.clear();
        }
    }

它在for循環(huán)中逐個(gè)去清除Segment下的數(shù)據(jù)胧后,如果不為空崔步,則調(diào)用segment的clear方法毅访。

基于這個(gè)方法攘残,有時(shí)候就會(huì)出現(xiàn)一種比較奇怪的現(xiàn)象:某一個(gè)線程剛存進(jìn)去的key-value,馬上就沒有了豹储,并且存進(jìn)去之后并沒有任何線程調(diào)用clear等類似方法。

結(jié)合clear的代碼思考一下不難理解,這種情況是在put一個(gè)value之前恰好有一個(gè)線程調(diào)用了clear方法蜕劝,在這個(gè)方法逐個(gè)清理segment時(shí),put的這個(gè)value剛好保存在了將要被clear但還沒有被clear的segment上轰异,所以這個(gè)value就會(huì)立馬被清理掉岖沛。

總結(jié)

ConcurrentHashMap 是一個(gè)并發(fā)情況下線程安全的HashMap,但是它的安全并不是那么絕對(duì)搭独,在一些特殊情況下仍然有可能會(huì)發(fā)生數(shù)據(jù)臟讀婴削,數(shù)據(jù)丟失等情況。所以在我們使用ConcurrentHashMap時(shí)一定要了解它的一些特性牙肝,這樣我們才能在使用它的時(shí)候不會(huì)產(chǎn)生一些意料之外的問題唉俗。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市配椭,隨后出現(xiàn)的幾起案子虫溜,更是在濱河造成了極大的恐慌,老刑警劉巖股缸,帶你破解...
    沈念sama閱讀 206,214評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件衡楞,死亡現(xiàn)場離奇詭異,居然都是意外死亡敦姻,警方通過查閱死者的電腦和手機(jī)瘾境,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來镰惦,“玉大人迷守,你說我怎么就攤上這事⊥耄” “怎么了盒犹?”我有些...
    開封第一講書人閱讀 152,543評(píng)論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我急膀,道長沮协,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評(píng)論 1 279
  • 正文 為了忘掉前任卓嫂,我火速辦了婚禮慷暂,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘晨雳。我一直安慰自己行瑞,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,224評(píng)論 5 371
  • 文/花漫 我一把揭開白布餐禁。 她就那樣靜靜地躺著血久,像睡著了一般。 火紅的嫁衣襯著肌膚如雪帮非。 梳的紋絲不亂的頭發(fā)上氧吐,一...
    開封第一講書人閱讀 49,007評(píng)論 1 284
  • 那天,我揣著相機(jī)與錄音末盔,去河邊找鬼筑舅。 笑死,一個(gè)胖子當(dāng)著我的面吹牛陨舱,可吹牛的內(nèi)容都是我干的翠拣。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評(píng)論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼游盲,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼误墓!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起益缎,我...
    開封第一講書人閱讀 36,956評(píng)論 0 259
  • 序言:老撾萬榮一對(duì)情侶失蹤优烧,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后链峭,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體畦娄,經(jīng)...
    沈念sama閱讀 43,441評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,925評(píng)論 2 323
  • 正文 我和宋清朗相戀三年弊仪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了熙卡。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 38,018評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡励饵,死狀恐怖驳癌,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情役听,我是刑警寧澤颓鲜,帶...
    沈念sama閱讀 33,685評(píng)論 4 322
  • 正文 年R本政府宣布表窘,位于F島的核電站,受9級(jí)特大地震影響甜滨,放射性物質(zhì)發(fā)生泄漏乐严。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,234評(píng)論 3 307
  • 文/蒙蒙 一衣摩、第九天 我趴在偏房一處隱蔽的房頂上張望昂验。 院中可真熱鬧,春花似錦艾扮、人聲如沸既琴。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽甫恩。三九已至,卻和暖如春酌予,著一層夾襖步出監(jiān)牢的瞬間磺箕,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評(píng)論 1 261
  • 我被黑心中介騙來泰國打工霎终, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留滞磺,地道東北人升薯。 一個(gè)月前我還...
    沈念sama閱讀 45,467評(píng)論 2 352
  • 正文 我出身青樓莱褒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親涎劈。 傳聞我的和親對(duì)象是個(gè)殘疾皇子广凸,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,762評(píng)論 2 345

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

  • 數(shù)據(jù)結(jié)構(gòu) ConcurrentHashMap 實(shí)現(xiàn)并發(fā)操作的原理 使用了鎖分段技術(shù):ConcurrentHashM...
    tomas家的小撥浪鼓閱讀 1,908評(píng)論 0 6
  • Java SE 基礎(chǔ): 封裝、繼承蛛枚、多態(tài) 封裝: 概念:就是把對(duì)象的屬性和操作(或服務(wù))結(jié)合為一個(gè)獨(dú)立的整體谅海,并盡...
    Jayden_Cao閱讀 2,099評(píng)論 0 8
  • 簡介 ConcurrentHashMap 是 Java concurrent 包的重要成員。本文將結(jié)合 Java ...
    翼徳閱讀 1,677評(píng)論 3 32
  • 給自己定下的日程行程全部擱置 前兩天雄心壯志許下的目標(biāo)好像也被丟下了 一年又一年沒有完成的減肥計(jì)劃被一頓好吃的又給...
    prayer_ft閱讀 180評(píng)論 0 0
  • 早起蹦浦,為孩子準(zhǔn)備午餐盒扭吁。前夜洗凈控干的餐盒,裝上洗凈的水果盲镶,切塊去核的果用保鮮膜仔細(xì)包好侥袜。備好餐盒,開始燒飯溉贿,在爐...
    暗香盈夢(mèng)閱讀 1,397評(píng)論 4 6