ConcurrentHashMap的源码分析-高低位原理分析
ConcurrentHashMap在做鏈表遷移時(shí),會(huì)用高低位來(lái)實(shí)現(xiàn),這里有兩個(gè)問(wèn)題要分析一下
1. 如何實(shí)現(xiàn)高低位鏈表的區(qū)分
假如我們有這樣一個(gè)隊(duì)列
第14個(gè)槽位插入新節(jié)點(diǎn)之后,鏈表元素個(gè)數(shù)已經(jīng)達(dá)到了8,且數(shù)組長(zhǎng)度為16,優(yōu)先通過(guò)擴(kuò)容來(lái)緩解鏈表過(guò)長(zhǎng)的問(wèn)題,擴(kuò)容這塊的圖解稍后再分析,先分析高低位擴(kuò)容的原理
假如當(dāng)前線程正在處理槽位為14的節(jié)點(diǎn),它是一個(gè)鏈表結(jié)構(gòu),在代碼中,首先定義兩個(gè)變量節(jié)點(diǎn)ln和hn,實(shí)際就是lowNode和HighNode,分別保存hash值的第x位為0和不等于0的節(jié)點(diǎn)
通過(guò)fn&n可以把這個(gè)鏈表中的元素分為兩類,A類是hash值的第X位為0,B類是hash值的第x位為不等于0(至于為什么要這么區(qū)分,稍后分析),并且通過(guò)lastRun記錄最后要處理的節(jié)點(diǎn)。最終要達(dá)到的目的是,A類的鏈表保持位置不動(dòng),B類的鏈表為14+16(擴(kuò)容增加的長(zhǎng)度)=30
我們把14槽位的鏈表單獨(dú)伶出來(lái),我們用藍(lán)色表示?fn&n=0的節(jié)點(diǎn),假如鏈表的分類是這樣
for (Node<K,V> p = f.next; p != null; p = p.next) { int b = p.hash & n;if (b != runBit) { runBit = b; lastRun = p; } }?通過(guò)上面這段代碼遍歷,會(huì)記錄runBit以及l(fā)astRun,按照上面這個(gè)結(jié)構(gòu),那么runBit應(yīng)該是藍(lán)色節(jié)點(diǎn),lastRun應(yīng)該是第6個(gè)節(jié)點(diǎn)
接著,再通過(guò)這段代碼進(jìn)行遍歷,生成ln鏈以及hn鏈
for (Node<K,V> p = f; p != lastRun; p = p.next) { int ph = p.hash; K pk = p.key; V pv = p.val; if ((ph & n) == 0) ln = new Node<K,V>(ph, pk, pv, ln); else hn = new Node<K,V>(ph, pk, pv, hn); }接著,通過(guò)CAS操作,把hn鏈放在i+n也就是14+16的位置,ln鏈保持原來(lái)的位置不動(dòng)。并且設(shè)置當(dāng)前節(jié)點(diǎn)為fwd,表示已經(jīng)被當(dāng)前線程遷移完了
setTabAt(nextTab, i, ln); setTabAt(nextTab, i + n, hn); setTabAt(tab, i, fwd);遷移完成以后的數(shù)據(jù)分布如下
?
總結(jié)
以上是生活随笔為你收集整理的ConcurrentHashMap的源码分析-高低位原理分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: ConcurrentHashMap的源码
- 下一篇: ConcurrentHashMap的源码