首页 > 编程语言 >ConcurrentHashMap源码阅读

ConcurrentHashMap源码阅读

时间:2024-08-14 16:17:16浏览次数:17  
标签:Node ConcurrentHashMap hash tab binCount 源码 阅读 key null

final V putVal(K key, V value, boolean onlyIfAbsent) {
    if (key == null || value == null) throw new NullPointerException();
    int hash = spread(key.hashCode());
    int binCount = 0;
    for (Node<K,V>[] tab = table;;) {
        Node<K,V> f; int n, i, fh;
        
        //如果数组未初始化,则初始化
        if (tab == null || (n = tab.length) == 0)
            tab = initTable();
        //计算元素的数组下标位置,为NULL的话直接CAS操作赋值。
        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {
            if (casTabAt(tab, i, null,
                         new Node<K,V>(hash, key, value, null)))
                break;                   // no lock when adding to empty bin
        }
        //如果是在扩容操作,则帮助扩容
        else if ((fh = f.hash) == MOVED)
            tab = helpTransfer(tab, f);
        else { //不能NULL,则为有元素数据
            V oldVal = null;
            
            //锁住头一个元素,进行操作
            synchronized (f) {
                //再次判断改节点是否是头节点
                if (tabAt(tab, i) == f) {
                    //表示链表节点
                    if (fh >= 0) {
                        binCount = 1;
                        for (Node<K,V> e = f;; ++binCount) {
                            K ek;
                            //判断hash相等 或key相同 更新对应的值
                            if (e.hash == hash &&
                                ((ek = e.key) == key ||
                                 (ek != null && key.equals(ek)))) {
                                oldVal = e.val;
                                if (!onlyIfAbsent)
                                    e.val = value;
                                break;
                            }
                            Node<K,V> pred = e;
                            
                            //如果下一个节点为NULL则赋值结束循环
                            if ((e = e.next) == null) {
                                pred.next = new Node<K,V>(hash, key,
                                                          value, null);
                                break;
                            }
                        }
                    }
                    //这里是树结构添加
                    else if (f instanceof TreeBin) {
                        Node<K,V> p;
                        binCount = 2;
                        if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,
                                                       value)) != null) {
                            oldVal = p.val;
                            if (!onlyIfAbsent)
                                p.val = value;
                        }
                    }
                }
            }
            if (binCount != 0) {
                //这里也是一样,>=8红黑树化
                if (binCount >= TREEIFY_THRESHOLD)
                    treeifyBin(tab, i);
                if (oldVal != null)
                    return oldVal;
                break;
            }
        }
    }
    addCount(1L, binCount);
    return null;
}
final V putVal(K key, V value, boolean onlyIfAbsent) {    if (key == null || value == null) throw new NullPointerException();    int hash = spread(key.hashCode());    int binCount = 0;    for (Node<K,V>[] tab = table;;) {        Node<K,V> f; int n, i, fh;        if (tab == null || (n = tab.length) == 0)            tab = initTable();        else if ((f = tabAt(tab, i = (n - 1) & hash)) == null) {            if (casTabAt(tab, i, null,                         new Node<K,V>(hash, key, value, null)))                break;                   // no lock when adding to empty bin        }        else if ((fh = f.hash) == MOVED)            tab = helpTransfer(tab, f);        else {            V oldVal = null;            synchronized (f) {                if (tabAt(tab, i) == f) {                    if (fh >= 0) {                        binCount = 1;                        for (Node<K,V> e = f;; ++binCount) {                            K ek;                            if (e.hash == hash &&                                ((ek = e.key) == key ||                                 (ek != null && key.equals(ek)))) {                                oldVal = e.val;                                if (!onlyIfAbsent)                                    e.val = value;                                break;                            }                            Node<K,V> pred = e;                            if ((e = e.next) == null) {                                pred.next = new Node<K,V>(hash, key,                                                          value, null);                                break;                            }                        }                    }                    else if (f instanceof TreeBin) {                        Node<K,V> p;                        binCount = 2;                        if ((p = ((TreeBin<K,V>)f).putTreeVal(hash, key,                                                       value)) != null) {                            oldVal = p.val;                            if (!onlyIfAbsent)                                p.val = value;                        }                    }                }            }            if (binCount != 0) {                if (binCount >= TREEIFY_THRESHOLD)                    treeifyBin(tab, i);                if (oldVal != null)                    return oldVal;                break;            }        }    }    addCount(1L, binCount);    return null;}

标签:Node,ConcurrentHashMap,hash,tab,binCount,源码,阅读,key,null
From: https://www.cnblogs.com/jichenghui/p/18359230

相关文章

  • 本地生活服务平台源码是什么?成功攻略分享!
    作为当前多家互联网重点布局项目,本地生活已然成为众多创业者心目中理想的创业赛道,本地生活服务商的申请热度更是因此持续飙升。不过,由于各大官方平台对其本地生活服务商的要求日益严苛,让不少创业者在被拒之门外的同时,开始考虑通过本地生活服务平台源码部署这一途径完成入局。......
  • 想要数字人直播平台赚钱,前期源码部署要注意哪些要点?
    随着人工智能时代的到来,数字人直播的应用频率不断升高,展现巨大收益潜力的同时,也让不少想要通过数字人源码厂商搭建数字人直播平台的创业者产生好奇,并开始从各方面打听数字人直播平台怎么赚钱等相关问题的答案。本期,我们将以数字人源码厂商灰豚所搭建的数字人直播平台为例,对市......
  • 在Centos系统源码安装postgreSQL数据库及postGIS扩展
    本次安装的各版本如下postgresql-13.5.targeos-3.10.2gdal-3.4.1proj-8.2.1postgis-3.2.1一、安装postgreSQL1.1安装包下载地址选postgresql-13.5.tar.gz。使用工具将下载好的包传到服务器。解压,进入解压目录[root@localhostlocal]#yuminstallgccreadline-develzlib-d......
  • 抽奖拼团系统app源码
    抽奖拼团系统是一种集合了抽奖和拼团两种营销方式的平台,旨在通过用户的互动和分享,提高品牌曝光度,增加销售量,同时为用户提供优惠和娱乐体验。以下是对抽奖拼团系统功能的案例分析一、系统概述抽奖拼团系统结合了抽奖活动的趣味性和拼团活动的社交性,让用户通过参与抽奖和发起或参......
  • 区块链通证系统源码
    区块链通证系统是一个基于区块链技术的系统,主要用于实现数字资产的发行、流通和管理。以下是对区块链通证系统功能的详细解释一、通证发行与管理发行通证:系统可以根据业务需求,设定通证的发行量、发行方案等,并通过智能合约实现自动化的发行过程。管理通证:系统提供全面的通证管......
  • JUC锁-AQS源码解读
    JUC锁-Java8中AbstractQueuedSynchronizer源码解读分析总体介绍AbstractQueuedSynchronizer概述在锁框架中,AbstractQueuedSynchronizer抽象类可以毫不夸张的说,占据着核心地位,它提供了一个基于FIFO队列,可以用于构建锁或者其他相关同步装置的基础框架。所以很有必要好好......
  • 科普文:Java基础系列之【java框架基础:字节码增强技术框架ASM#ClassReader实现原理及源
    1概述ASM是Java中比较流行的用来读写字节码的类库,用来基于字节码层面对代码进行分析和转换。在读写的过程中可以加入自定义的逻辑以增强或修改原来已编译好的字节码,比如CGLIB用它来实现动态代理。ASM被设计用于在运行时对Java类进行生成和转换,当然也包括离线处理。ASM短小精......
  • kimi为论文参考文献阅读和撰写提供的几点帮助
    学境思源,一键生成论文初稿:AcademicIdeas-学境思源AI论文写作随着暑期已至,即将步入新学期的同学们准备好了吗?面对未来职业道路和学术研究的挑战,如何有效利用假期进行学习和充电成为关键。今天我们将分享如何借助Kimi完成参考文献的阅读和撰写,从而提升学术研究的效率和质量......
  • JSP花店业务管理系统的设计与实现4vcg5--(程序+源码+数据库+调试部署+开发环境)
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统功能:用户,商家,场合分类,花卉信息,商家回复,用户咨询开题报告内容一、项目背景与意义随着人们对生活品质追求的提升,花卉消费日益增长,传统花店管理模式已难......
  • JSP河南口腔医疗诊所线上服务系统a11h1--程序+源码+数据库+调试部署+开发环境
    本系统(程序+源码+数据库+调试部署+开发环境)带论文文档1万字以上,文末可获取,系统界面在最后面。系统程序文件列表系统功能:用户,医生,科室,医生信息,挂号信息,药品信息,取消挂号开题报告内容一、课题名称河南口腔医疗诊所线上服务系统设计与实现二、研究背景与意义随着互......