ConcurrentHashMap源码阅读#initTable

private final Node[] initTable() {
        Node[] 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[] nt = (Node[])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)