代码之家  ›  专栏  ›  技术社区  ›  JGFMK

Java Concurrent Hashmap initTable()为什么是try/finally块?

  •  0
  • JGFMK  · 技术社区  · 4 年前

    here )'

    /**
     * Initializes table, using the size recorded in sizeCtl.
     */
    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.compareAndSetInt(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;
    }
    

    有人能解释一下为什么需要try块吗?

    3 回复  |  直到 4 年前
        1
  •  3
  •   rzwitserloot    4 年前

    未检查的异常和错误作为一个概念存在。如果你打电话 .put() 在ConcurrentHashMap上,内存非常紧张,该映射可能会尝试生成一个数组,而调用可能会失败,并出现OutOfMemoryError。代码仍将继续(可能是在捕获这个的catch块),对该映射的引用仍然存在。如果发生这种情况之后,由于sizeCtl有一个损坏的值,映射崩溃并完全无效,这将有点糟糕。

    关键是最后一个块,它恢复 sizeCtl 价值观。它用于各种事情,值得注意的是包括管理哪个线程可以访问。如果它没有,任何其他看跌期权都将永远旋转。

    这一点的相关性(例如,在这里,一个丢弃的发生频率,与删除“尝试”和“最终”并以 sizeCtl = sc; 没有try/finally的额外开销)是低的,但是如果它是相关的,它是非常相关的。

        2
  •  0
  •   Den-Jason    4 年前

    首先

    if ((sc = sizeCtl) < 0)
        Thread.yield(); // lost initialization race; just spin
    

    sizeCtl

    if (U.compareAndSetInt(this, SIZECTL, sc, -1)
    

    这是一个原子操作-如果另一个线程在第一次和第二次检查之间抓住它,则 if 不会被带走。

    try-finally 用于确保互斥体被释放( 重置为其原始值),无论是否发生异常(例如分配新节点的内存不足-或是否存在适用于映射的唯一限制)。