ConcurrentHashMap的源码分析-resizeStamp
這塊邏輯要理解起來,也有一點(diǎn)復(fù)雜。
resizeStamp用來生成一個和擴(kuò)容有關(guān)的擴(kuò)容戳,具體有什么作用呢?我們基于它的實現(xiàn)來做一個分析
static final int resizeStamp(int n) { return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1)); }Integer.numberOfLeadingZeros?這個方法是返回?zé)o符號整數(shù)n最高位非0位前面的0的個數(shù)
比如10的二進(jìn)制是?0000 0000 0000 0000 0000?0000 0000 1010
那么這個方法返回的值就是28?
根據(jù)resizeStamp的運(yùn)算邏輯,我們來推演一下,假如n=16,那么resizeStamp(16)=32796轉(zhuǎn)化為二進(jìn)制是
[0000 0000 0000 0000?1000 0000 0001 1100]
接著再來看,當(dāng)?shù)谝粋€線程嘗試進(jìn)行擴(kuò)容的時候,會執(zhí)行下面這段代碼?
U.compareAndSwapInt(this,?SIZECTL, sc, (rs <<?RESIZE_STAMP_SHIFT) +?2)?
rs左移16位,相當(dāng)于原本的二進(jìn)制低位變成了高位1000 0000 0001 1100?0000 0000 0000?0000?
然后再+2?=1000 0000 0001 1100?0000 0000 0000 0000+10=1000 0000 0001 1100?0000 0000?0000 0010
高16位代表擴(kuò)容的標(biāo)記、低16位代表并行擴(kuò)容的線程數(shù)?高RESIZE_STAMP_BITS位?低RESIZE_STAMP_SHIFT位?擴(kuò)容標(biāo)記?并行擴(kuò)容線程數(shù)
這樣來存儲有什么好處呢??
1. 首先在CHM中是支持并發(fā)擴(kuò)容的,也就是說如果當(dāng)前的數(shù)組需要進(jìn)行擴(kuò)容操作,可以由多個線程來共同負(fù)責(zé),這塊后續(xù)會單獨(dú)講
2. 可以保證每次擴(kuò)容都生成唯一的生成戳,每次新的擴(kuò)容,都有一個不同的n,這個生成戳就是根據(jù)n來計算出來的一個數(shù)字,n不同,這個數(shù)字也不同
第一個線程嘗試擴(kuò)容的時候,為什么是+2?
因為1表示初始化,2表示一個線程在執(zhí)行擴(kuò)容,而且對sizeCtl的操作都是基于位運(yùn)算的,所以不會關(guān)心它本身的數(shù)值是多少,只關(guān)心它在二進(jìn)制上的數(shù)值,而sc+1會在低16位上加1。?
?
總結(jié)
以上是生活随笔為你收集整理的ConcurrentHashMap的源码分析-resizeStamp的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ConcurrentHashMap的源码
- 下一篇: ConcurrentHashMap的源码