ConcurrentHashMap源码(二)--initTable

在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
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值