ConcurrentHashMap.initTable(),为什么两次检查table是否为空?
ConcurrentHashMap.initTable(), why check table is null twice?
我正在学习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;
}
多个线程可能会竞争执行此操作(请参阅“初始化竞争”评论)。
转述代码:
while(uninitialized) {
acquire_lock(); //compareAndSwapInt...
if(uninitialized) {
do_init();
}
}
外部检查是一种便宜的“解锁”测试。内部的是万一其他人已经在 while
和 compareAndSwapInt
之间成功了。
我正在学习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;
}
多个线程可能会竞争执行此操作(请参阅“初始化竞争”评论)。
转述代码:
while(uninitialized) {
acquire_lock(); //compareAndSwapInt...
if(uninitialized) {
do_init();
}
}
外部检查是一种便宜的“解锁”测试。内部的是万一其他人已经在 while
和 compareAndSwapInt
之间成功了。