有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

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) 个答案

  1. # 1 楼答案

    多个线程可能会竞争这样做(请参阅“初始化竞争”注释)

    要解释代码,请执行以下操作:

    while(uninitialized) {
        acquire_lock(); //compareAndSwapInt...
        if(uninitialized) {
            do_init();
        }
    }
    

    外部检查是一种廉价的“解锁”测试。在whilecompareAndSwapInt之间,如果其他人已经成功了,则使用内部的方法