在ConcurrentHashMap
的源代码中,有一个名为resizeStamp
的方法,代码为:
static final int resizeStamp(int n) {
return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
}
此代码如何运作?
答案 0 :(得分:0)
简短回答:将
sc
作为(resizeStamp(n) << RESIZE_STAMP_SHIFT)
的结果,sc
的高16位告诉该信息,至少有一个线程对容量{{1 }},低16位告诉信息,有多少个标准并发程序正在同时调整大小。
说明:
首先,查看n
的文档
resizeStamp(n)
所以这个功能显然可以做两件事
/**
* Returns the stamp bits for resizing a table of size n.
* Must be negative when shifted left by RESIZE_STAMP_SHIFT.
*/
static final int resizeStamp(int n) {
return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
}
tmpReuslt
的第16位设为1(请注意:tmpResult
是一个等于16的常量)因此resizeStamp返回格式为RESIZE_STAMP_BITS
的32位int值
如文档所述,返回结果“当左移RESIZE_STAMP_SHIFT时必须为负”。
很明显,当第16位设置为1时,向左移动RESIZE_STAMP_SHIFT时,重用的最高位将为1,这使其成为负数。
然后,第二个问题来了,为什么要这样做,请在ConcurrentHashMap中检出0000 0000 0000 0000 1xxx xxx xxxx xxxx
函数
addCount(long x, int check)
resizeStamp用于通过操作 // some code here
if (check >= 0) {
Node<K,V>[] tab, nt; int n, sc;
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
(n = tab.length) < MAXIMUM_CAPACITY) {
int rs = resizeStamp(n);
if (sc < 0) {
if ((sc >>> RESIZE_STAMP_SHIFT) != rs || sc == rs + 1 ||
sc == rs + MAX_RESIZERS || (nt = nextTable) == null ||
transferIndex <= 0)
break;
if (U.compareAndSwapInt(this, SIZECTL, sc, sc + 1))
transfer(tab, nt);
}
else if (U.compareAndSwapInt(this, SIZECTL, sc,
(rs << RESIZE_STAMP_SHIFT) + 2))
transfer(tab, null);
s = sumCount();
}
}
在ConcurrentHashMap中提升sizeCtl的值。
resizeStamp函数确保{1> (rs << RESIZE_STAMP_SHIFT) + 2
取负值
sizeCtl
成功执行。
U.compareAndSwapInt(this, SIZECTL, sc,(rs << RESIZE_STAMP_SHIFT) + 2)
的高16位可以说明以下信息:在sizeCtl
大小的情况下,正在进行大小调整操作