Rob*_*Hou 5 java java.util.concurrent
在转移方法中,判断扩展终止(或帮助转移线程完成)的条件是if (i < 0 || i >= n || i + n >= nextn) {。我知道i < 0这个条件意味着所有的 bin 都被分配了,但我不明白其他两个条件的含义: i >= n和i + n >= nextn
是否i >= n考虑数据溢出?(-2147483648 - 1 = 2147483647);
是i + n >= nextn一样的i >= n吗?(我不这么认为)
private final void transfer(Node<K,V>[] tab, Node<K,V>[] nextTab) {
int n = tab.length, stride;
//...
int nextn = nextTab.length;
ForwardingNode<K,V> fwd = new ForwardingNode<K,V>(nextTab);
boolean advance = true;
boolean finishing = false; // to ensure sweep before committing nextTab
for (int i = 0, bound = 0;;) {
Node<K,V> f; int fh;
while (advance) {
int nextIndex, nextBound;
if (--i >= bound || finishing)
advance = false;
else if ((nextIndex = transferIndex) <= 0) {
i = -1;
advance = false;
}
else if (U.compareAndSwapInt
(this, TRANSFERINDEX, nextIndex,
nextBound = (nextIndex > stride ?
nextIndex - stride : 0))) {
bound = nextBound;
i = nextIndex - 1;
advance = false;
}
}
if (i < 0 || i >= n || i + n >= nextn) {
int sc;
if (finishing) {
nextTable = null;
table = nextTab;
sizeCtl = (n << 1) - (n >>> 1);
return;
}
if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) {
if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT)
return;
finishing = advance = true;
i = n; // recheck before commit
}
}
//...
}
Run Code Online (Sandbox Code Playgroud)
从逻辑上讲,这是一段死代码,我认为这可能是编码/调试期间的边界检测。
\n从数学的角度来看,如果 i >= n,那么
\nwhile (advance) {\n int nextIndex, nextBound;\n if (--i >= bound || finishing)\n advance = false;\n else if ((nextIndex = transferIndex) <= 0) { //here is the only chance to update nextIndex\n i = -1;\n advance = false;\n }\n else if (U.compareAndSwapInt\n (this, TRANSFERINDEX, nextIndex,\n nextBound = (nextIndex > stride ?\n nextIndex - stride : 0))) {\n bound = nextBound;\n i = nextIndex - 1;\n advance = false;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n人们可能会怀疑 volatile 变量的更新顺序,例如 nextTable/table/sizeCtl,也是不可能的。 \n
\n因为在调整大小结束时,它们更新如下:
while (advance) {\n int nextIndex, nextBound;\n if (--i >= bound || finishing)\n advance = false;\n else if ((nextIndex = transferIndex) <= 0) { //here is the only chance to update nextIndex\n i = -1;\n advance = false;\n }\n else if (U.compareAndSwapInt\n (this, TRANSFERINDEX, nextIndex,\n nextBound = (nextIndex > stride ?\n nextIndex - stride : 0))) {\n bound = nextBound;\n i = nextIndex - 1;\n advance = false;\n }\n}\nRun Code Online (Sandbox Code Playgroud)\n并且所有transfer的输入都严格检查table/nextTable/sizeCtl和transferIndex。\n
\n同样,无法泄漏部分更新到transfer。
所以 i+n >= nextn
\n| 归档时间: |
|
| 查看次数: |
231 次 |
| 最近记录: |