ConcurrentHashMap源码(二)--initTable

来源:互联网 发布:大数据技术及应用 编辑:程序博客网 时间:2024/06/14 13:15

在ConcurrentHashMap的put方法中,第一次添加元素的时候table是空的(使用空的构造函数),就会执行initTable方法。


下面就来看一下jdk8是怎么初始化这个table的,如何保证并发不出问题。


关于unsafe.compareAndSwap的用法,可以参见我以前的博客 AtomicInteger分析--自实现无锁并发。



private final Node<K,V>[] initTable() {        Node<K,V>[] tab; int sc;//这个有个死循环,        while ((tab = table) == null || tab.length == 0) {//2.sizeCtl何时为0?看后面            if ((sc = sizeCtl) < 0)                Thread.yield(); // lost initialization race; just spin//1.这里有个if,如果没进这个if,则继续循环//什么时候没进这个if呢?//-就是unsafe.compareAndSwapInt失败的时候,//什么时候失败呢?//-当其他的线程也对sizeCtl进行了修改(内存里实际的值与手上拿的不一样,这个时候就返回false了。svn一样)//2.如果成功了,则进入if,同时,内存中的sizeCtl的值也被修改成了-1,这个时候就可以看到1处做的判断:如果小于0,则放弃此次执行//3.如果未成功,那继续while://-这个时候要么其他的线程已经将table初始化好了,table!=null,直接返回table就行了//  -要么其他线程正在初始化这个表,此时的sizeCtl是-1.所以放弃此次执行。(等待其他线程)            else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {                try {                    if ((tab = table) == null || tab.length == 0) {//这里就是初始化一个table数组                        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设置为新的table的容量(而不是-1)                    sizeCtl = sc;                }//初始化完成了,那就break。                break;            }        }        return tab;    }


0 0
原创粉丝点击