java.util.concurrent.ConcurrentHashMap#initTable方法中双重检测是否有必要

这篇博客探讨了ConcurrentHashMap在多线程环境下的初始化问题,特别是双重检查锁定(Double-Check Locking)在初始化table时的必要性。文章通过一个场景解释了为何在table为null时需要双重检测,防止多个线程重复初始化,确保线程安全。
摘要由CSDN通过智能技术生成

读ConcurrentHashMap源码有一点疑问。

    /**
     * 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.compareAndSwapInt(this, SIZECTL, sc, -1)) {//CAS竞争成功开始初始化
                try {
                    if ((tab = table) == null || tab.length == 0) {//双重检测在这个地方有必要吗
                        int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                        Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                        table = tab = nt;
                        sc = n - (n >>> 2);
                    }
                } finally {
                    sizeCtl = sc;
                }
                break;
            }
        }
        return tab;
    }

重温了一下单例模式的双重检测,发现是有必要的。

假设一个场景,一个新的Map,table为null,两个线程A B同时做put操作,同时进入initTable方法,都发现table为null,然后A线程CAS成功,进入初始化,此时B线程让出CPU时间;A线程初始化结束,这时sizeCtl值位12,然后B线程重新获得CPU时间,由于sizeCtl=12,B线程CAS成功会再次进行初始化。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值