ConcurrentHashMap之initTable

前提

  • ConcurrentHashMap是线程安全的
  • ConcurrentHashMap数据结构:数组+hash算法+链表(jdk1.8之前)+树结构(jdk1.8以后)
  • 当前jdk版本1.8

作用

  • map初始化,设置table大小

业务逻辑

  • 1,如果当前table数组是空的,进入初始化,否则table,不需要初始化
  • 2,sizeCtl的意思,当前table是否正在初始化,如果是,则让出线程
  • 3,开始进入初始化,并修改sizeCtl的值,防止其他线程初始化,原子层面修改sizeCtl值,可以快速修改,并同步数据
  • 修改sizeCtl的值为-1
  • 开始初始化大小
  • 初始化结束,修改sizeCtl的值为sc,默认清空下sizeCtl的值为12

代码

initTable

/**
 * Table initialization and resizing control.  When negative, the
 * table is being initialized or resized: -1 for initialization,
 * else -(1 + the number of active resizing threads).  Otherwise,
 * when table is null, holds the initial table size to use upon
 * creation, or 0 for default. After initialization, holds the
 * next element count value upon which to resize the table.
 */
private transient volatile int sizeCtl;
/**
 * The default initial table capacity.  Must be a power of 2
 * (i.e., at least 1) and at most MAXIMUM_CAPACITY.
 */
private static final int DEFAULT_CAPACITY = 16;
/**
 * Initializes table, using the size recorded in sizeCtl.
 */
private final Node<K,V>[] initTable() {
    Node<K,V>[] tab; int sc;
    //1,如果当前table数组是空的
    while ((tab = table) == null || tab.length == 0) {
    	//2,sizeCtl是否有线程占用,如果是,则让出CPU,进入就绪状态,默认值为0,-1指的是正在初始化
        if ((sc = sizeCtl) < 0)
            Thread.yield(); // lost initialization race; just spin
        //3,修改sc的值为-1,原子层面修改,compareAndSwapInt本地方法,具体如何实现,可以下载相关源码查看
        else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
            try {
                if ((tab = table) == null || tab.length == 0) {
                	//如果 sizeCtl>0 初始化大小为sizeCtl,否则初始化大小为16
                    int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                    @SuppressWarnings("unchecked")
                    Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                    table = tab = nt;
                    //sc赋值,如果n为16,则sc = 16-16/4 = 12,
                    sc = n - (n >>> 2);
                }
            } finally {
            	//赋值给sizeCtl,初始化结束,sizeCtl的值>0
                sizeCtl = sc;
            }
            break;
        }
    }
    return tab;
}

sizeCtl的作用

  • 在多线程的情况下,多个线程同时初始化同一个table,此时使用sizeCtl进行标识,初始化的开始,初始化中,初始化结束的状态,防止多次初始化

compareAndSwapInt的作用

  • 底层方法实现
  • 主要作用是修改sc的值,以达到防止其他线程同时初始化
  • 后期会把compareAndSwapInt相关的源码贴出来
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值