ConcurrentHashMap resizeStamp方法如何工作?

时间:2017-11-08 09:23:18

标签: java concurrency

ConcurrentHashMap的源代码中,有一个名为resizeStamp的方法,代码为:

static final int resizeStamp(int n) {
    return Integer.numberOfLeadingZeros(n) | (1 << (RESIZE_STAMP_BITS - 1));
}

此代码如何运作?

1 个答案:

答案 0 :(得分:0)

  

简短回答:将sc作为(resizeStamp(n) << RESIZE_STAMP_SHIFT)的结果,sc的高16位告诉该信息,至少有一个线程对容量{{1 }},低16位告诉信息,有多少个标准并发程序正在同时调整大小。

说明:

首先,查看n的文档

resizeStamp(n)

所以这个功能显然可以做两件事

  1. 将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)); }
  2. 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函数确保{ (rs << RESIZE_STAMP_SHIFT) + 2取负值

sizeCtl

成功执行。

  • U.compareAndSwapInt(this, SIZECTL, sc,(rs << RESIZE_STAMP_SHIFT) + 2) 的高16位可以说明以下信息:在sizeCtl大小的情况下,正在进行大小调整操作