java ConcurrentHashMap。initTable(),为什么检查表两次为空?
我正在学习java源代码,当我阅读ConcurrentHashMap源代码时,我对initTable()方法感到困惑,为什么要检查(tab = table) == null || tab.length == 0
两次,首先在while()
中,然后在if()
中。我无法想象在什么情况下需要第二次检查
我想可能是因为JVM重新排序代码,将sizeCtl = sc;
放在Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
前面。这只是我的猜测,我不知道这是否正确
谁能解释一下吗,谢谢
private final Node<K,V>[] initTable() {
Node<K,V>[] tab; int sc;
while ((tab = table) == null || tab.length == 0) {
if ((sc = sizeCtl) < 0)
Thread.yield(); // lost initialization race; just spin
else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
try {
if ((tab = table) == null || tab.length == 0) {
int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
@SuppressWarnings("unchecked")
Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
table = tab = nt;
sc = n - (n >>> 2);
}
} finally {
sizeCtl = sc;
}
break;
}
}
return tab;
}
# 1 楼答案
多个线程可能会竞争这样做(请参阅“初始化竞争”注释)
要解释代码,请执行以下操作:
外部检查是一种廉价的“解锁”测试。在
while
和compareAndSwapInt
之间,如果其他人已经成功了,则使用内部的方法