能否移除ConcurrentHashMap transfer()方法中的i >= n判断?
关于ConcurrentHashMap transfer()方法中
i >= n || i + n >= nextn判断的疑问 我正在研究java.util.concurrent.ConcurrentHashMap中的transfer()方法,想请教是否可以直接移除方法中的i >= n || i + n >= nextn判断?
相关代码片段如下:
for (int i = 0, bound = 0;;) { Node<K,V> f; int fh; while (advance) { int nextIndex, nextBound; if (--i >= bound || finishing) // always decreasing advance = false; else if ((nextIndex = transferIndex) <= 0) { i = -1; // obviously less than n advance = false; } else if (U.compareAndSetInt (this, TRANSFERINDEX, nextIndex, nextBound = (nextIndex > stride ? nextIndex - stride : 0))) { bound = nextBound; i = nextIndex - 1; // will be guaranteed to be less than n advance = false; } } if (i < 0 || i >= n || i + n >= nextn) { // why keep any thing other than i < 0
从数学角度看,i作为局部变量,不可能超过旧表长度n;另外相关讨论也指出这部分是死代码。我是不是忽略了Java内存模型(JMM)中需要保留该判断的相关点?
可以安全移除i >= n || i + n >= nextn这两个条件,只保留i < 0即可,原因如下:
- 代码逻辑层面:
i的所有赋值和更新路径都被严格限制在小于n的范围内:- 初始
i=0,而扩容时旧表长度n至少为1,必然小于n; - 通过
transferIndex分配任务时,i = nextIndex - 1,nextIndex从初始值n递减分配,因此nextIndex -1一定小于n; - 循环中
--i只会让i的值更小,不可能反向增大到超过n; - 唯一会让
i变为负数的情况是transferIndex <=0时设置i=-1。
- 初始
- JMM层面:这部分判断涉及的
n(旧表长度)和nextn(新表长度)在扩容初始化后就固定不变,局部变量i的可见性完全由当前线程控制,不存在因内存可见性问题导致i超出范围的情况。 - 这部分代码确实是死代码,不会被执行到,移除后对程序逻辑没有任何影响。
内容的提问来源于stack exchange,提问作者ng.newbie
相关产品推荐
相关产品推荐

