ConcurrentHashMap線程安全原理

原文

總結(jié):

分段機(jī)制:segment,每段加reentrantLock可重入鎖
定位元素:1 找segment數(shù)組下標(biāo) 2 找segment的HashEntry數(shù)組下標(biāo)
get方法:不需要加鎖,value值使用了volatile關(guān)鍵字修飾
put方法:hash計(jì)算段---鎖定段---hash計(jì)算HashEntry數(shù)組---若超多閾值---擴(kuò)容---釋放;put過程中會(huì)modCount+1,為了后續(xù)的計(jì)算大小
size()方法:為了求Map的大小,需要全局鎖,但是性能差;于是采用modCount計(jì)算器,用于記錄段的大??;
ConcurrentHashMap的弱一致性:clear時(shí),是不加鎖的,所以多線程中,可能出現(xiàn)數(shù)據(jù)不一致;

因?yàn)闆]有全局的鎖,在清除完一個(gè)segments之后,正在清理下一個(gè)segments的時(shí)候,已經(jīng)清理segments可能又被加入了數(shù)據(jù),因此clear返回的時(shí)候,ConcurrentHashMap中是可能存在數(shù)據(jù)的。因此,clear方法是弱一致的。

ConcurrentHashMap的弱一致性主要是為了提升效率,是一致性與效率之間的一種權(quán)衡。要成為強(qiáng)一致性,就得到處使用鎖,甚至是全局鎖,這就與Hashtable和同步的HashMap一樣了。

而在迭代時(shí),ConcurrentHashMap使用了不同于傳統(tǒng)集合的快速失敗迭代器(見之前的文章《JAVA API備忘---集合》)的另一種迭代方式,我們稱為弱一致迭代器。在這種迭代方式中,當(dāng)iterator被創(chuàng)建后集合再發(fā)生改變就不再是拋出ConcurrentModificationException,取而代之的是在改變時(shí)new新的數(shù)據(jù)從而不影響原有的數(shù)據(jù),iterator完成后再將頭指針替換為新的數(shù)據(jù),這樣iterator線程可以使用原來老的數(shù)據(jù),而寫線程也可以并發(fā)的完成改變,更重要的,這保證了多個(gè)線程并發(fā)執(zhí)行的連續(xù)性和擴(kuò)展性,是性能提升的關(guān)鍵。

詳情:

ConcurrentHashMap基本思想:


image.png
image.png

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


image.png

ConcurrentHashMap的初始化

image.png
image.png

ConcurrentHashMap的get方法


image.png

ConcurrentHashMap的put方法


image.png

ConcurrentHashMap的size方法


image.png

ConcurrentHashMap的弱一致性
因?yàn)闆]有全局的鎖,在清除完一個(gè)segments之后,正在清理下一個(gè)segments的時(shí)候,已經(jīng)清理segments可能又被加入了數(shù)據(jù),因此clear返回的時(shí)候,ConcurrentHashMap中是可能存在數(shù)據(jù)的。因此,clear方法是弱一致的。
舉2個(gè)比較簡單的例子就可以看出ConcurrentHashMap的弱一致性。

第一個(gè),就是clear方法。假設(shè)線程1執(zhí)行到Segment[0].clear()的時(shí)候,Segment[0]中的元素元素已經(jīng)被clear,但是線程2此時(shí)可以在Segment[0]中增加元素(clear不需要加鎖),這樣線程1執(zhí)行結(jié)束的時(shí)候就ConcurrentHashMap并不是空的。

image.png

第二個(gè)例子,判斷key是否存在,不存在則進(jìn)行put。假設(shè)線程1判斷key不存在后掛起,線程2判斷key也不存在,然后線程2執(zhí)行put操作,之后線程1執(zhí)行put操作,此時(shí)線程2讀取到的會(huì)是線程1設(shè)置的值而不是線程2設(shè)置的值。當(dāng)然此時(shí)應(yīng)該是應(yīng)用putIfAbsent方法。

小結(jié)

ConcurrentHashMap在設(shè)計(jì)思路對效率和一致性上的平衡以及一些lock-free的方法非常值得借鑒,同時(shí)注意雖然類本身是線程安全的,但是不要認(rèn)為使用該類就一定是線程安全的。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容