亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

ConcurrentHashMap學(xué)習(xí)

mayaohua / 1846人閱讀

摘要:與和是一一對(duì)應(yīng)的,對(duì)充當(dāng)鎖的角色,每當(dāng)對(duì)數(shù)組的數(shù)據(jù)進(jìn)行修改時(shí),首先要獲取對(duì)應(yīng)的鎖解決散列沖突的方式是采用分離鏈表法分散鏈表法使用鏈表解決沖突,將散列值相同的元素都保存到一個(gè)鏈表中。負(fù)載因子,默認(rèn)為。

一、為什么要用ConcurrentHashMap?

1、HashMap線程不安全,并且進(jìn)行put操作會(huì)導(dǎo)致死循環(huán)(由于HashMap的Entry鏈表形成環(huán)形數(shù)據(jù)結(jié)構(gòu),Entry下的next節(jié)點(diǎn)永遠(yuǎn)不為空)
2、HashTable多線程效率低下,主要表現(xiàn)在數(shù)據(jù)操作方法頭采用synchronized互斥鎖,使得其他線程訪問(wèn)同步方法會(huì)進(jìn)入阻塞或者是輪詢狀態(tài)(就是線程會(huì)無(wú)限循環(huán)查看鎖是否被釋放)
3、ConcurrentHashMap的鎖分段技術(shù)可提升并發(fā)訪問(wèn)效率(表現(xiàn)在吞吐量)

二、結(jié)構(gòu)

解析:Segment是一種可重入鎖,在ConcurrentHashMap中扮演鎖的角色,HashEntry則是用于存儲(chǔ)鍵值對(duì)數(shù)據(jù)。ConcurrentHashMap與Segment和HashEntry是一一對(duì)應(yīng)的,Segment對(duì)HashEntry充當(dāng)鎖的角色,每當(dāng)對(duì)HashEntry數(shù)組的數(shù)據(jù)進(jìn)行修改時(shí),首先要獲取對(duì)應(yīng)的Segment鎖
解決散列沖突的方式是采用分離鏈表法:
分散鏈表法使用鏈表解決沖突,將散列值相同的元素都保存到一個(gè)鏈表中。當(dāng)查詢的時(shí)候,首先找到元素所在的鏈表,然后遍歷鏈表查找對(duì)應(yīng)的元素,也就是會(huì)根據(jù)key定位到鏈表的某個(gè)位置,所以不管是hashMap還是concurrentHashMap相同key是只取最后插入的值

圖片來(lái)自 http://faculty.cs.niu.edu/~fr...

三、初始化

capacity:當(dāng)前數(shù)組容量,始終保持 2^n,可以擴(kuò)容,擴(kuò)容后數(shù)組大小為當(dāng)前的 2 倍,默認(rèn)為16,即默認(rèn)允許16個(gè)線程同時(shí)訪問(wèn)。
loadFactor:負(fù)載因子,默認(rèn)為 0.75。
threshold:擴(kuò)容的閾值,等于 capacity * loadFactor
初始化Segment數(shù)組,該長(zhǎng)度ssize是通過(guò)concurrencyLevel計(jì)算得出,需要能通過(guò)按位與的散列算法來(lái)定位數(shù)組的索引,故必須要保證Segment的長(zhǎng)度為2的N次方,故concurrencyLevel為14、15、16,ssize都等于15,即容器鎖的格式也是16
初始化segment,initialCapacity為ConcurrentHashMap初始化容量,loadfactor是每個(gè)segment的負(fù)載因子

四、定位Segment

由于ConcurrentHashMap使用分段鎖Segment來(lái)保護(hù)不同段的數(shù)據(jù),那么在插入和讀取元素的時(shí)候,必須先通過(guò)Wang/Jenkins hash的變種算法對(duì)元素的hashCode進(jìn)行再次散列
那么為什么需要再次散列呢?
為了減少散列沖突,使得元素能夠均勻分布在不同的segment中,從而達(dá)到提高容器的存取效率,那么不再次散列會(huì)出現(xiàn)什么結(jié)果?
會(huì)導(dǎo)致不同數(shù)值它的散列值可能會(huì)相同,從而導(dǎo)致所有數(shù)值都存在同一個(gè)segment中,從而導(dǎo)致segment失去分段鎖的意義并且存取緩慢
如果進(jìn)行再次散列,那么所有的數(shù)值都會(huì)散列開(kāi),之前的問(wèn)題迎刃而解

五、get、put、size操作

ConcurrentHashMap高效的原因之一在于get操作不需要加鎖,因?yàn)樗泄蚕碜兞慷级x成volatile,能夠保證在多線程之間的可見(jiàn)性,能夠被多線程同時(shí)讀,并且保證不會(huì)讀到過(guò)期值,并且由volatile修飾的共享變量均不需要回寫主內(nèi)存
put操作時(shí)由于對(duì)共享變量進(jìn)行了寫的操作,故必須加鎖,那么put方法首先會(huì)定位到segment(因?yàn)閟egment相當(dāng)于裝載元素的桶),然后進(jìn)行插入操作,操作分為2步:
1、在插入元素之前會(huì)先判斷是否需要擴(kuò)容(所有容器都是需要判斷擴(kuò)容),做法是如果capacity *loadFactor大于threshold則擴(kuò)容,
2、擴(kuò)容多少呢?首先會(huì)創(chuàng)建一個(gè)容量為原來(lái)2倍的數(shù)組,將原有元素進(jìn)行散列后插入新的數(shù)組,為了高效,只會(huì)針對(duì)某個(gè)segment進(jìn)行擴(kuò)容
那這個(gè)就是負(fù)載因子的作用,這個(gè)操作和HashMap不一致,HashMap是在插入完之后進(jìn)行判斷是否需要擴(kuò)容,就會(huì)導(dǎo)致如果下次沒(méi)有插入數(shù)據(jù),那么這個(gè)空間就浪費(fèi)了,在jdk1.8還做了部分修改
size操作:就是為了統(tǒng)計(jì)segment的所有大小,那么segment的count是個(gè)全局變量是用volatile修飾,最快速的做法是,把所有的segment的count加起來(lái),但是如果在這期間出現(xiàn)了修改操作,那么count的統(tǒng)計(jì)就不精確了,如果把segment的put、remove、clean全部鎖住,那么效率太低,目前的做法是,嘗試2次不鎖住segment來(lái)統(tǒng)計(jì)count,如果統(tǒng)計(jì)過(guò)程中出現(xiàn)容器變化,那么就加鎖,來(lái)統(tǒng)計(jì),ConcurrentHashMap是如何知道統(tǒng)計(jì)過(guò)程中容器發(fā)生了變化,用modCount變量,在put、remove、clean方法里操作元素前會(huì)將modCount進(jìn)行加1,比較前后變化

jdk1.8不再采用segment作為鎖的粒度,而是直接將HashEntry作為鎖,從而降低鎖的粒度、
jdk1.8使用內(nèi)置鎖synchronized來(lái)代替重入鎖ReentrantLock
因?yàn)榱6冉档土?,在相?duì)而言的低粒度加鎖方式,synchronized并不比ReentrantLock差,在粗粒度加鎖中ReentrantLock可能通過(guò)Condition來(lái)控制各個(gè)低粒度的邊界,更加的靈活,而在低粒度中,Condition的優(yōu)勢(shì)就沒(méi)有了
JVM的開(kāi)發(fā)團(tuán)隊(duì)從來(lái)都沒(méi)有放棄synchronized,而且基于JVM的synchronized優(yōu)化空間更大,使用內(nèi)嵌的關(guān)鍵字比使用API更加自然
在大量的數(shù)據(jù)操作下,對(duì)于JVM的內(nèi)存壓力,基于API的ReentrantLock會(huì)開(kāi)銷更多的內(nèi)存,雖然不是瓶頸,但是也是一個(gè)選擇依據(jù)

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://www.ezyhdfw.cn/yun/77470.html

相關(guān)文章

  • [學(xué)習(xí)筆記-Java集合-7] Map - ConcurrentHashMap 源碼分析(一)

    摘要:簡(jiǎn)介是的線程安全版本,內(nèi)部也是使用數(shù)組鏈表紅黑樹(shù)的結(jié)構(gòu)來(lái)存儲(chǔ)元素。相比于同樣線程安全的來(lái)說(shuō),效率等各方面都有極大地提高。中的關(guān)鍵字,內(nèi)部實(shí)現(xiàn)為監(jiān)視器鎖,主要是通過(guò)對(duì)象監(jiān)視器在對(duì)象頭中的字段來(lái)表明的。 簡(jiǎn)介 ConcurrentHashMap是HashMap的線程安全版本,內(nèi)部也是使用(數(shù)組 + 鏈表 + 紅黑樹(shù))的結(jié)構(gòu)來(lái)存儲(chǔ)元素。 相比于同樣線程安全的HashTable來(lái)說(shuō),效率等各方...

    SoapEye 評(píng)論0 收藏0
  • [學(xué)習(xí)筆記-Java集合-8] Map - ConcurrentHashMap 源碼分析(二)

    摘要:那么,如果之后不是簡(jiǎn)單的操作,而是還有其它業(yè)務(wù)操作,之后才是,比如下面這樣,這該怎么辦呢其它業(yè)務(wù)操作這時(shí)候就沒(méi)辦法使用提供的方法了,只能業(yè)務(wù)自己來(lái)保證線程安全了,比如下面這樣其它業(yè)務(wù)操作這樣雖然不太友好,但是最起碼能保證業(yè)務(wù)邏輯是正確的。 刪除元素 刪除元素跟添加元素一樣,都是先找到元素所在的桶,然后采用分段鎖的思想鎖住整個(gè)桶,再進(jìn)行操作。 public V remove(Objec...

    2501207950 評(píng)論0 收藏0
  • 趣談ConcurrentHashMap

    摘要:最近準(zhǔn)備面試,一談到基礎(chǔ),大部分面試官上來(lái)就數(shù)據(jù)結(jié)構(gòu)素質(zhì)三連與區(qū)別,底層數(shù)據(jù)結(jié)構(gòu),為什么能保證線程安全。數(shù)組順序存儲(chǔ),內(nèi)存連續(xù),查詢快,插入刪除效率稍微低,不過(guò)現(xiàn)在略有改善。而在開(kāi)始,是由和的方式去實(shí)現(xiàn)高并發(fā)下的線程安全。 最近準(zhǔn)備面試,一談到j(luò)ava基礎(chǔ),大部分面試官上來(lái)就java數(shù)據(jù)結(jié)構(gòu)素質(zhì)三連:ArrayList與LinkedList區(qū)別,HashMap底層數(shù)據(jù)結(jié)構(gòu),Concur...

    Travis 評(píng)論0 收藏0
  • ConcurrentHashMap基于JDK1.8源碼剖析

    摘要:下面我來(lái)簡(jiǎn)單總結(jié)一下的核心要點(diǎn)底層結(jié)構(gòu)是散列表數(shù)組鏈表紅黑樹(shù),這一點(diǎn)和是一樣的。是將所有的方法進(jìn)行同步,效率低下。而作為一個(gè)高并發(fā)的容器,它是通過(guò)部分鎖定算法來(lái)進(jìn)行實(shí)現(xiàn)線程安全的。 前言 聲明,本文用的是jdk1.8 前面章節(jié)回顧: Collection總覽 List集合就這么簡(jiǎn)單【源碼剖析】 Map集合、散列表、紅黑樹(shù)介紹 HashMap就是這么簡(jiǎn)單【源碼剖析】 LinkedHas...

    sanyang 評(píng)論0 收藏0
  • ConcurrentHashMap中tabAt、setTabAt方法的意義所在

    摘要:總結(jié)中針對(duì)數(shù)組的訪問(wèn)和賦值的意義應(yīng)該是在于越過(guò)對(duì)數(shù)組操作的包裝,進(jìn)而達(dá)到優(yōu)化性能的目的。以上為拋磚引玉。。參考鏈接知乎請(qǐng)問(wèn)數(shù)組的行為是如何實(shí)現(xiàn)的 在學(xué)習(xí)ConcurrentHashMap時(shí)發(fā)現(xiàn),源碼中對(duì)table數(shù)組的元素進(jìn)行操作時(shí),使用了三個(gè)封裝好的原子操作方法,如下: /* ---------------- Table element access -------------- *...

    GeekGhc 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<