• ConsurrentHashMap InitTable 疑问与思考


    ConsurrentHashMap InitTable 疑问与思考

    ConsurrentHashMap 作为单机下经常使用的一个线程安全Map值得我们学习一下,以下其初始化的过程的代码,以及学习过程中遇到的疑惑与自己的思考

     private final Node<K,V>[] initTable() {
            Node<K,V>[] tab; int sc;
            while ((tab = table) == null || tab.length == 0) {
                // 此时有其他线程正在初始化,礼让
                if ((sc = sizeCtl) < 0)
                    Thread.yield(); // lost initialization race; just spin
                else if (U.compareAndSwapInt(this, SIZECTL, sc, -1)) {
                    try {
                        if ((tab = table) == null || tab.length == 0) {
                            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 = sc;
                    }
                    break;
                }
            }
            return tab;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    1、多线程下该方法不加锁时如何保证线程安全的

    通常意义下的加锁,都是去检查一个东西是否被“其他”持有,如果被持有则本次加锁尝试失败。这里也是同样的思路,通过判断sc是否小于零来判断当前是否有其他线程操作,如果有其他线程操作到下面sc会被修改成**-1**来表示被加锁,同时CAS的操作保证了只能由一个线程修改成功,即只有一个线程能获得锁

    2、为什么使用while 而不是if

    initTable 的方法是为了完成初始化返回一个node数组,所以没有**“获取锁”线程需要陷入等待,等待其他线程完成初始化,所以该方法使用了while来让没有“获取锁”**的线程不断循环等待。

    3、为什么使用Thread.yield(),而不是return、sleep

    第二个问题说到需要循环等待所有自然不可能提前return,那为什么不用sleep,因为我们并不知道另一个线程什么时候完成初始化,也就不知道sleep多少秒,多了、少了都不合适,所以干脆就让出cpu时间片,等下一次再看看,如果其他线程完成了初始化就返回,否则重复以上。这其实就是源码中注释表达的含义:lost initialization race; just spin,退出竞争,不断自旋。

  • 相关阅读:
    【大数据】-- dataworks 创建odps 的 hudi 外表
    apple pencil一定要买吗?Ipad电容笔推荐品牌
    (附源码)小程序 交通违法举报系统 毕业设计 242045
    【工作记录】基于spiderflow+ocr实现图片验证码识别@20230906
    CentOS 30分钟部署免费在线客服系统
    【若依框架2】前后端分离版本添加功能页
    MAC 配置 Maven
    网络基础(一)
    【更换yarn的位置】解决yarn和nodejs不在同一盘下产生的某些命令应用失败问题
    SQL优化记录
  • 原文地址:https://blog.csdn.net/weixin_43779268/article/details/126025274