ConcurrentHashMap的源码分析-fullAddCount源码分析
生活随笔
收集整理的這篇文章主要介紹了
ConcurrentHashMap的源码分析-fullAddCount源码分析
小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
fullAddCount主要是用來(lái)初始化CounterCell,來(lái)記錄元素個(gè)數(shù),里面包含擴(kuò)容,初始化等操作
private final void fullAddCount(long x, boolean wasUncontended) {int h; //獲取當(dāng)前線程的probe的值,如果值為0,則初始化當(dāng)前線程的probe的值,probe就是隨機(jī)數(shù) if ((h = ThreadLocalRandom.getProbe()) == 0) { ThreadLocalRandom.localInit(); // force initialization h = ThreadLocalRandom.getProbe(); wasUncontended = true; // 由于重新生成了probe,未沖突標(biāo)志位設(shè)置為true } boolean collide = false; // True if last slot nonempty for (;;) {//自旋 CounterCell[] as; CounterCell a; int n; long v; // 說(shuō)明counterCells已經(jīng)被初始化過(guò)了,我們先跳過(guò)這個(gè)代碼,先看初始化部分 if ((as = counterCells) != null && (n = as.length) > 0) { if ((a = as[(n - 1) & h]) == null) {// 通過(guò)該值與當(dāng)前線程probe求與,獲得cells的下標(biāo)元素,和hash 表獲取索引是一樣的 if (cellsBusy == 0) { // cellsBusy=0表示counterCells不在初始化或者擴(kuò)容狀態(tài)下 CounterCell r = new CounterCell(x); // 構(gòu)造一個(gè)CounterCell的值,傳入元素個(gè)數(shù) if (cellsBusy == 0 &&// 通過(guò)cas設(shè)置cellsBusy標(biāo)識(shí),防止其他線程來(lái)對(duì)counterCells并發(fā)處理 U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { boolean created = false; try { // Recheck under lock CounterCell[] rs; int m, j; // 將初始化的r對(duì)象的元素個(gè)數(shù)放在對(duì)應(yīng)下標(biāo)的位置 if ((rs = counterCells) != null && (m = rs.length) > 0 && rs[j = (m - 1) & h] == null) { rs[j] = r; created = true; } } finally {//恢復(fù)標(biāo)志位 cellsBusy = 0; } if (created)//創(chuàng)建成功,退出循環(huán) break; continue;//說(shuō)明指定cells下標(biāo)位置的數(shù)據(jù)不為空,則進(jìn)行下一次循環(huán) } } collide = false; } //說(shuō)明在addCount方法中cas失敗了,并且獲取probe的值不為空 else if (!wasUncontended) // CAS already known to fail wasUncontended = true; //設(shè)置為未沖突標(biāo)識(shí),進(jìn)入下一次自旋 //由于指定下標(biāo)位置的cell值不為空,則直接通過(guò)cas進(jìn)行原子累加,如果成功,則直接退出 else if (U.compareAndSwapLong(a, CELLVALUE, v = a.value, v + x))// break; //如果已經(jīng)有其他線程建立了新的counterCells或者CounterCells大于CPU核心數(shù)(很巧妙,線程的并發(fā)數(shù)不會(huì)超過(guò)cpu核心數(shù)) else if (counterCells != as || n >= NCPU) collide = false; //設(shè)置當(dāng)前線程的循環(huán)失敗不進(jìn)行擴(kuò)容 else if (!collide)//恢復(fù)collide狀態(tài),標(biāo)識(shí)下次循環(huán)會(huì)進(jìn)行擴(kuò)容 collide = true; //進(jìn)入這個(gè)步驟,說(shuō)明CounterCell數(shù)組容量不夠,線程競(jìng)爭(zhēng)較大,所以先設(shè)置一個(gè)標(biāo)識(shí)表示為正在擴(kuò)容 else if (cellsBusy == 0 && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { try { if (counterCells == as) {// Expand table unless stale //擴(kuò)容一倍 2變成4,這個(gè)擴(kuò)容比較簡(jiǎn)單 CounterCell[] rs = new CounterCell[n << 1]; for (int i = 0; i < n; ++i) rs[i] = as[i]; counterCells = rs; } } finally { cellsBusy = 0;//恢復(fù)標(biāo)識(shí) } collide = false; continue;//繼續(xù)下一次自旋 } h = ThreadLocalRandom.advanceProbe(h);//更新隨機(jī)數(shù)的值 } 初始化 CounterCells 數(shù)組//cellsBusy=0表示沒有在做初始化,通過(guò)cas更新cellsbusy的值標(biāo)注當(dāng)前線程正在做初 始化操作 else if (cellsBusy == 0 && counterCells == as && U.compareAndSwapInt(this, CELLSBUSY, 0, 1)) { boolean init = false; try { // Initialize table if (counterCells == as) { CounterCell[] rs = new CounterCell[2]; //初始化容量為2 rs[h & 1] = new CounterCell(x);//將x也就是元素的個(gè)數(shù)放在指定的數(shù)組 下標(biāo)位置 counterCells = rs;//賦值給counterCells init = true;//設(shè)置初始化完成標(biāo)識(shí) } } finally { cellsBusy = 0;//恢復(fù)標(biāo)識(shí) } if (init) break; } //競(jìng)爭(zhēng)激烈,其它線程占據(jù)cell 數(shù)組,直接累加在base變量中 else if (U.compareAndSwapLong(this, BASECOUNT, v = baseCount, v + x)) break; // Fall back on using base } }?
總結(jié)
以上是生活随笔為你收集整理的ConcurrentHashMap的源码分析-fullAddCount源码分析的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ConcurrentHashMap的源码
- 下一篇: ConcurrentHashMap的源码