ConcurrentHashMap的源码分析-扩容结束以后的退出机制

如果线程扩容结束,那么需要退出,就会执行transfer方法的如下代码

//i<0说明已经遍历完旧的数组,也就是当前线程已经处理完所有负责的bucket 
if (i < 0 || i >= n || i + n >= nextn) { 
	int sc; 
	if (finishing) {//如果完成了扩容 
		nextTable = null;//删除成员变量 
		table = nextTab;//更新table数组 
		sizeCtl = (n << 1) - (n >>> 1);//更新阈值(32*0.75=24) 
		return; 
	}
	// sizeCtl 在迁移前会设置为 (rs << RESIZE_STAMP_SHIFT) + 2 
	// 然后,每增加一个线程参与迁移就会将 sizeCtl 加 1, 
	// 这里使用 CAS 操作对 sizeCtl 的低16位进行减 1,代表做完了属于自己的任务 
	if (U.compareAndSwapInt(this, SIZECTL, sc = sizeCtl, sc - 1)) { 
		第一个扩容的线程,执行transfer方法之前,会设置 sizeCtl = (resizeStamp(n) << RESIZE_STAMP_SHIFT) + 2) 后续帮其扩容的线程,执行transfer方法之前,会设置 sizeCtl = sizeCtl+1 
		每一个退出transfer的方法的线程,退出之前,会设置 sizeCtl = sizeCtl-1 
		那么最后一个线程退出时:必然有 
		sc == (resizeStamp(n) << RESIZE_STAMP_SHIFT) + 2),即 (sc - 2) == resizeStamp(n) << RESIZE_STAMP_SHIFT 
		// 如果 sc - 2 不等于标识符左移 16 位。如果他们相等了,说明没有线程在帮助他们扩容了。也就是说,扩容结束了。 
		if ((sc - 2) != resizeStamp(n) << RESIZE_STAMP_SHIFT) 
		return; 
		// 如果相等,扩容结束了,更新 finising 变量 
		finishing = advance = true; 
		// 再次循环检查一下整张表 
		i = n; // recheck before commit 
	} 
} 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值