微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Java并发Hashmap initTable为什么try / finally块?

如何解决Java并发Hashmap initTable为什么try / finally块?

我一直在看下面的代码(来自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块吗?

解决方法

未经检查的异常和错误作为一个概念存在。如果您在ConcurrentHashMap上调用.put(),而您的内存确实紧缺,则该映射可能会尝试创建一个数组,并且该调用可能会失败,并显示OutOfMemoryError。代码仍将继续(可能在捕获该代码的catch块处),并且对该映射的引用仍然存在。如果在此之后发生地图崩溃并由于sizeCtl值损坏而完全失效的情况,那会有点遗憾。

关键是finally块将恢复sizeCtl的值。这用于各种用途,值得注意的包括管理哪个线程获得访问权限。如果没有,其他任何看跌期权将永远旋转。

与此相关(例如,在这里多久发生一次可抛出事件,而不是删除“ try”和“ finally”并仅以sizeCtl = sc;结尾,而没有try / final的额外开销)较低,但如果相关,则非常相关。

,

这是一种互斥锁-并具有双重检查锁。

首先

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

检查sizeCtl互斥。如果该值小于零,则说明有人已将其抓住,因此我们只需要稍等片刻即可。

如果它为零(或更大),则有机会获得锁。因此,执行了“比较并交换”操作:

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

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

如果CAS成功,则该方法将负责释放互斥量。因此,无论是否发生异常(例如,内存不足分配新节点-或是否存在异常),都使用try-finally确保互斥体被释放(sizeCtl重置为其原始值)。是否适用于地图)。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。