JAVA并发容器源码分析【二】ConcurrentHashMap分析之初始化

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】
免费领取10G资料包与项目实战视频资料

文章首发于:clawhub.club


JDK8的ConcurrentHashMap的初始化源码及注释:

        /**
         * Initializes table, using the size recorded in sizeCtl.
         * 使用sizeCtl中记录的大小初始化表。
         */
        private final Node<K,V>[] initTable() {
            Node<K,V>[] tab; int sc;
            //只要表为空,就一直循环
            while ((tab = table) == null || tab.length == 0) {
                //如果sizeCtl小于0,
                if ((sc = sizeCtl) < 0)
                    //用了yield方法后,该线程就会把CPU时间让掉,让其他或者自己的线程执行(也就是谁先抢到谁执行)
                    Thread.yield(); // lost initialization race; just spin 失去了初始化CPU竞争;只是自旋
                else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) { //如果SIZECTL与sc相同,则把SIZECTL设置为-1,即当前线程获取到了初始化的工作。
                    try {
                        //再次确认 表为空
                        if ((tab = table) == null || tab.length == 0) {
                            //如果初始化size大于0,则n为sc,否则为16.
                            int n = (sc > 0) ? sc : DEFAULT_CAPACITY;
                            //创建n个Node数组
                            @SuppressWarnings("unchecked")
                            Node<K,V>[] nt = (Node<K,V>[])new Node<?,?>[n];
                            //table指向空数组
                            table = tab = nt;
                            // 如果 n 为 16 的话,那么这里 sc = 12
                            // 其实就是 0.75 * n
                            sc = n - (n >>> 2);
                        }
                    } finally {
                        //sizeCtl重新定义新的值,用于扩容。
                        sizeCtl = sc;
                    }
                    break;
                }
            }
            return tab;
        }

由源码可知:初始化的代码比较简单,通过初始化数组,之后将sizeCtl赋值。
这里涉及到的知识点:

  1. Thread.yield():使当前线程从执行状态(运行状态)变为可执行态(就绪状态)。
  2. U.compareAndSwapInt(this, SIZECTL, sc, -1)和SIZECTL = U.objectFieldOffset(k.getDeclaredField("sizeCtl")):通过反射获取sizeCtl,再通过CAS设置其值。
  3. sc = n - (n >>> 2):其实就是 0.75 * n,扩容阈值。

这个方法并发通过对SIZECTL+CAS实现。


来源:https://www.jianshu.com/p/a75d196731c0

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » JAVA并发容器源码分析【二】ConcurrentHashMap分析之初始化

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏