如何解决为什么在JDK12 ConcurrentHashMap中删除了这种条件“sc >>> RESIZE_STAMP_SHIFT!= rs”?
在addCount方法(也包括helpTransfer方法)中,停止容量扩展的第一个条件是(sc >>> RESIZE_STAMP_SHIFT) != rs
,我知道JDK8中存在一个错误:probable bug in logic of ConcurrentHashMap.addCount()。但是在JDK12中,我想知道的是:为什么要删除此条件(sc >>> RESIZE_STAMP_SHIFT) != rs
?我认为这种情况在JDK12中应该变成(sc >>> RESIZE_STAMP_SHIFT) != (rs >>> RESIZE_STAMP_SHIFT)
。
在JDK8中:
private final void addCount(long x,int check) {
//...
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;
//...
}
//...
}
}
}
在JDK12中:
private final void addCount(long x,int check) {
//...
if (check >= 0) {
Node<K,nt;
int n,sc;
while (s >= (long)(sc = sizeCtl) && (tab = table) != null &&
(n = tab.length) < MAXIMUM_CAPACITY) {
int rs = resizeStamp(n) << RESIZE_STAMP_SHIFT;
if (sc < 0) {
if (sc == rs + MAX_RESIZERS || sc == rs + 1 ||
(nt = nextTable) == null || transferIndex <= 0)
break;
//...
}
//...
}
}
}
我也注意到了Bug in the logic of ConcurrentHashMap.addCount() when used in Threads的问题,但是它仍然处于打开状态
解决方法
(sc >>> RESIZE_STAMP_SHIFT) != rs
表示 tab.length
在赋值 (sc = sizeCtl
) 后发生变化。在这种情况下,必须有另一个线程完成或正在完成调整大小(在传输方法中)。
-
完成后,
nextTable == null
将为true
。 -
当它完成时,
sizeCtl
将与当前的不同,不同的sizeCtl
在不同的调整轮次。
然后 (U.compareAndSetInt(this,SIZECTL,sc,sc + 1)
) 将是假的,下一次迭代中的此线程将中断 sc > 0
的 while 或帮助下一次调整大小或重试。
private final void transfer(Node<K,V>[] tab,Node<K,V>[] nextTab) {
...
if (finishing) {
nextTable = null;
// table changed after "nextTable = null"。
table = nextTab;
sizeCtl = (n << 1) - (n >>> 1);
return;
}
...
}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。