ConcurrentHashMap.initTable(),为什么两次检查table为null?

pet*_*har 5 java concurrenthashmap

我正在学习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;
    }
Run Code Online (Sandbox Code Playgroud)

小智 7

多个线程可能会竞争执行此操作(请参阅“初始化竞争”注释)。

解释一下代码:

while(uninitialized) {
    acquire_lock(); //compareAndSwapInt...
    if(uninitialized) {
        do_init();
    }
}
Run Code Online (Sandbox Code Playgroud)

外部检查是一种廉价的“解锁”测试。内部的一个是为了防止其他人在while和 之间已经成功compareAndSwapInt