美文网首页
ConcurrentHashMap源码阅读#initTable

ConcurrentHashMap源码阅读#initTable

作者: 丫头可乐 | 来源:发表于2020-03-23 03:45 被阅读0次
    private final Node<K,V>[] initTable() {
            Node<K,V>[] tab;
            int sc;
            //如果tab一直为null,就一直进行循环,直到当前线程获取到Node数组
            while ((tab = table) == null || tab.length == 0) {
                //sizeCtl为-1时,表示有其他线程正在进行初始化
               
                if ((sc = sizeCtl) < 0)
    //这里yield()方法会告知调度器说我要让出CPU,重新恢复到就绪状态。
    //至于能不能成功让出cpu,也不一定。
    //如果能成功让出,当前线程恢复到ready状态,在等待再次运行的过程当中。
    //其他的线程可能已经完成初始化了。这样就可以直接返回tab。
    //如果没有让出,那就继续进行while循环,等待其他线程完成初始化工作。
    
                    Thread.yield(); // lost initialization race; just spin
    //这里使用CAS原子操作对sizeCtl进行修改。将原来的值,改成-1。这里就说明了,如果sizeCtl被成功修改成了-1,就表明有一个线程正在进行初始化。其他的线程再进来的时候,拿到sizeCtl=-1。然后yield出CPU。
                else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
                    try {
    /**
    *设有两个线程t1,t2都在进行初始化操作。
    *这个时候,t1已经完成了初始化,这个时候sizeCtl根据下面的逻辑应该是12。
    *而这时候,t2刚刚进入到while循环中,这时候,会重新给sizeCtl赋值成-1。
    *赋值成功后,如果没有空判断,则又会重新初始化一遍。
    */
                        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 {
    /**
    *After initialization, holds the next element count value upon which to resize the table.
    *
    *根据这句话,我们可以得知,在完成初始化后,sizeCtl的值被设置称为0.75*capacity
    */
    
                        sizeCtl = sc;
                    }
                    break;
                }
            }
            return tab;
        }
    

    相关文章

      网友评论

          本文标题:ConcurrentHashMap源码阅读#initTable

          本文链接:https://www.haomeiwen.com/subject/ikqiyhtx.html