ConcurrentHashMap

目標(biāo):

1.capacity,concurrencyLevel:容量與并發(fā)級(jí)別的偿衰,如何促發(fā)擴(kuò)容狗超,ConcurrentHashMap兩個(gè)字段的意義:segmentMask,segmentShift

2.jdk1.6/jdk1.7不同之處,jdk1.6

count是volitile的

3.理解ConcurrentHashMap為何支持高并發(fā)谴忧,對(duì)此作了哪些優(yōu)化很泊,segment, volitile, happens-before, HashEntry final value?

4.記住默認(rèn)容量、并發(fā)級(jí)別沾谓、加載因子

5.測(cè)試不同并發(fā)級(jí)別下的性能測(cè)試委造,出測(cè)試結(jié)果

6.實(shí)現(xiàn)一個(gè)簡(jiǎn)易的ConcurrentHashMap示例


總結(jié):

1、字段的含義:

1.1 capacity是指整個(gè)map的容量均驶,即所有segment中的hashEntry的數(shù)昏兆,map最終都是在hashEntry的中存儲(chǔ)數(shù)據(jù)的

1.2 concurrencyLevel:并發(fā)級(jí)別,即ConcurrentHashMap中segment的數(shù)量妇穴,concurrencyLevel = segmentSize爬虱,并發(fā)時(shí)鎖的即是segment隶债,segmentSize 必須是 2^n ,可以參考HashMap的size也是必須是2^n

1.3 segmentShift,segmentMask:segment偏移量,segment掩碼跑筝,在segmentFor時(shí)用到死讹,定位到具體某個(gè)segment。segmentMask = segmentSize - 1曲梗,segmentShift= 32 - sshift,

sshift=n,n是segmentSize =

2^n中的n

如concurrencyLevel = 16 => sshift=4,segmentMask=15 =>

segmentShift= 32 - 4赞警,再哈希后的數(shù)最大是32位二進(jìn)制數(shù)據(jù),所以是32 -

sshift虏两,segmentFor:

hash >>> segmentShift & segmentMask 意思是讓高4位參與到hash運(yùn)算中

2愧旦、jdk1.6/jdk1.7: https://my.oschina.net/hosee/blog/675884

最大的區(qū)別在于,jdk1.6應(yīng)用volatile關(guān)鍵字 happens-before原則實(shí)現(xiàn)的讀/寫(xiě)一直定罢,jdk1.6中用的UNSAFE的原子操作來(lái)實(shí)現(xiàn)的

3笤虫、高并發(fā)的原理

3.1 分離鎖

無(wú)需鎖整個(gè)ConcurrentHashMap,只在修改結(jié)構(gòu)的時(shí)候祖凫,只需鎖住分段segment

3.2 用 volatile 變量協(xié)調(diào)讀寫(xiě)線(xiàn)程間的內(nèi)存可見(jiàn)性琼蚯,使得讀(get)可以不加鎖

讀操作的高效之處在于整個(gè)get過(guò)程不需要加鎖,除非讀到的值是空的才會(huì)加鎖重讀蝙场。get操作是如何做到不加鎖的呢凌停?原因是它的get方法里將要使用的共享變量都定義成volatile,如用于統(tǒng)計(jì)當(dāng)前Segement大小的?????? count字段和用于存儲(chǔ)值的HashEntry的value售滤。定義成volatile的變量罚拟,能夠在線(xiàn)程之間保持可見(jiàn)性,能夠被多線(xiàn)程同時(shí)讀完箩,并且保證不會(huì)讀到過(guò)期的值赐俗,但是只能被單線(xiàn)程寫(xiě)(有一種情況可以被多線(xiàn)程寫(xiě),就是寫(xiě)入的值不依賴(lài)于原值)弊知,在get操作里只需要讀不需要寫(xiě)共享變量count和value阻逮,所以可以不用加鎖。之所以不會(huì)讀到過(guò)期的值秩彤,是根據(jù)java內(nèi)存模型的happen before原則叔扼,對(duì)volatile字段的寫(xiě)入操作先于讀操作,即使兩個(gè)線(xiàn)程同時(shí)修改和獲取volatile變量漫雷,get操作也能拿到最新的值瓜富,這是用volatile替換鎖的經(jīng)典應(yīng)用場(chǎng)景(這是JDK1.6的實(shí)現(xiàn))transient

volatile int count;volatile V value;

3.3 用 HashEntery 對(duì)象的不變性來(lái)降低讀操作對(duì)加鎖的需求

HashEntry 中的 key,hash降盹,next 都聲明為 final与柑。這意味著,不能把節(jié)點(diǎn)添加到鏈接的中間和尾部,也不能在鏈接的中間和尾部刪除節(jié)點(diǎn)价捧。這個(gè)特性可以保證:在訪(fǎng)問(wèn)某個(gè)節(jié)點(diǎn)時(shí)丑念,這個(gè)節(jié)點(diǎn)之后的鏈接不會(huì)被改變。這個(gè)特性可以大大降低處理鏈表時(shí)的復(fù)雜性结蟋。

3.4 總結(jié)

基于通常情形而優(yōu)化:

在實(shí)際的應(yīng)用中脯倚,散列表一般的應(yīng)用場(chǎng)景是:除了少數(shù)插入操作和刪除操作外,絕大多數(shù)都是讀取操作椎眯,而且讀操作在大多數(shù)時(shí)候都是成功的挠将。正是基于這個(gè)前提,ConcurrentHashMap 針對(duì)讀操作做了大量的優(yōu)化编整。通過(guò) HashEntry 對(duì)象的不變性和用 volatile型變量協(xié)調(diào)線(xiàn)程間的內(nèi)存可見(jiàn)性,使得大多數(shù)時(shí)候乳丰,讀操作不需要加鎖就可以正確獲得值掌测。這兩個(gè)特性相配合,不僅減少了請(qǐng)求同一個(gè)鎖的頻率(讀操作一般不需要加鎖就能夠成功獲得值)产园,也減少了持有同一個(gè)鎖的時(shí)間(只有讀到 value 域的值為 null 時(shí) , 讀線(xiàn)程才需要加鎖后重讀)

ConcurrentHashMap 的高并發(fā)性主要來(lái)自于三個(gè)方面:

用分離鎖實(shí)現(xiàn)多個(gè)線(xiàn)程間的更深層次的共享訪(fǎng)問(wèn)汞斧。

用 HashEntery 對(duì)象的不變性來(lái)降低執(zhí)行讀操作的線(xiàn)程在遍歷鏈表期間對(duì)加鎖的需求。

通過(guò)對(duì)同一個(gè)Volatile 變量的寫(xiě) / 讀訪(fǎng)問(wèn)什燕,協(xié)調(diào)不同線(xiàn)程間讀/ 寫(xiě)操作的內(nèi)存可見(jiàn)性

4粘勒、默認(rèn)容量:

DEFAULT_INITIAL_CAPACITY

= 16;

DEFAULT_CONCURRENCY_LEVEL

= 16;

DEFAULT_LOAD_FACTOR = 0.75f;

MAXIMUM_CAPACITY

= 1 << 30;

MAX_SEGMENTS =

1 << 16;

5、屎即?Google ConcurrentHashMapperformancetest

6庙睡、?


參考:

Jdk1.6

http://www.infoq.com/cn/articles/ConcurrentHashMap/

https://www.ibm.com/developerworks/cn/java/java-lo-concurrenthashmap/

jdk1.7

https://my.oschina.net/hosee/blog/639352

https://my.oschina.net/hosee/blog/675884/

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末技俐,一起剝皮案震驚了整個(gè)濱河市乘陪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌雕擂,老刑警劉巖啡邑,帶你破解...
    沈念sama閱讀 217,542評(píng)論 6 504
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異井赌,居然都是意外死亡谤逼,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,822評(píng)論 3 394
  • 文/潘曉璐 我一進(jìn)店門(mén)仇穗,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)流部,“玉大人,你說(shuō)我怎么就攤上這事仪缸」蠛” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,912評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀(guān)的道長(zhǎng)宾茂。 經(jīng)常有香客問(wèn)我瓷马,道長(zhǎng),這世上最難降的妖魔是什么跨晴? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,449評(píng)論 1 293
  • 正文 為了忘掉前任欧聘,我火速辦了婚禮,結(jié)果婚禮上端盆,老公的妹妹穿的比我還像新娘怀骤。我一直安慰自己,他們只是感情好焕妙,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,500評(píng)論 6 392
  • 文/花漫 我一把揭開(kāi)白布蒋伦。 她就那樣靜靜地躺著,像睡著了一般焚鹊。 火紅的嫁衣襯著肌膚如雪痕届。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 51,370評(píng)論 1 302
  • 那天末患,我揣著相機(jī)與錄音研叫,去河邊找鬼。 笑死璧针,一個(gè)胖子當(dāng)著我的面吹牛嚷炉,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播探橱,決...
    沈念sama閱讀 40,193評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼申屹,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了走搁?” 一聲冷哼從身側(cè)響起独柑,我...
    開(kāi)封第一講書(shū)人閱讀 39,074評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎私植,沒(méi)想到半個(gè)月后忌栅,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,505評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡曲稼,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,722評(píng)論 3 335
  • 正文 我和宋清朗相戀三年索绪,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片贫悄。...
    茶點(diǎn)故事閱讀 39,841評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡瑞驱,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出窄坦,到底是詐尸還是另有隱情唤反,我是刑警寧澤凳寺,帶...
    沈念sama閱讀 35,569評(píng)論 5 345
  • 正文 年R本政府宣布,位于F島的核電站彤侍,受9級(jí)特大地震影響肠缨,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜盏阶,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,168評(píng)論 3 328
  • 文/蒙蒙 一晒奕、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧名斟,春花似錦脑慧、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,783評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至楞卡,卻和暖如春霜运,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背蒋腮。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,918評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留藕各,地道東北人池摧。 一個(gè)月前我還...
    沈念sama閱讀 47,962評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像激况,于是被迫代替她去往敵國(guó)和親作彤。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,781評(píng)論 2 354

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