Java技术债务Java技术债务

  •  首页
  •  分类
  •  归档
  •  标签
  • 博客日志
  • 资源分享
  •  友链
  •  关于本站
注册
登录

ConcurrentHashMap的原理分析

Java

JDK1.7:

底层数据结构:数组(sgement)、数组(HashEntry)、链表(HashEntry节点)

两个主要的内部类:

class Segment内部类,继承ReentrantLock,有一个HashEntry数组,用来存储链表头结点

class HashEntry 定义的节点,里面存储的数据和下一个节点

主要方法:

get()方法:

1、第一次哈希 找到 对应的Segment段,调用Segment中的get方法

2、再次哈希找到对应的链表,

3、最后在链表中查找。

put()方法:

1、首先确定段的位置,调用Segment中的put方法:

2、加锁

3、检查当前Segment数组中包含的HashEntry节点的个数,如果超过阈值就重新hash

4、然后再次hash确定放的链表。

5、在对应的链表中查找是否相同节点,如果有直接覆盖,如果没有将其放置链表尾部

重哈希方式 :重点:

重哈希的方式 :只是对 Segments对象中的Hashentry数组进行重哈希

线程安全:

分段锁 对整个桶数组进行了分割分段(Segment),每一把锁只锁容器其中一部分数据,多线程访问容器里不同数据段的数据,就不会存在锁竞争,提高并发访问率。

ConcurrentHashMap的原理分析 - Java技术债务

JDK1.8:

底层数据结构:Synchronized、CAS、Node

Node数组使用来存放树或者链表的头结点,当一个链表中的数量到达一个数目时,会使查询速率降低,所以到达一定阈值时,会将一个链表转换为一个红黑二叉树,通告查询的速率。

线程安全方式:

使用的是优化的synchronized 关键字同步代码块 和 cas操作了维护并发。 通过使用Synchroized关键字来同步代码块,而且只是在put方法中加锁,在get方法中没有加锁 在加锁时是使用头结点作为同步锁对象。

**效率:**简化结构,put和get不用二次哈希,一把锁只锁住一个链表或者一棵树,并发效率更加提升。

主要属性:

ConcurrentHashMap的原理分析 - Java技术债务

主要方法:

1、构造方法:

构造方法并没有直接new出来一个Node的数组,只是检查数值之后确定了容量大小。

2、put方法:

步骤:

 检查Key或者Value是否为null,
 得到Kye的hash值
 如果Node数组是空的,此时才初始化 initTable(),
 如果找的对应的下标的位置为空,直接new一个Node节点并放入, break;
 如果对应头结点不为空, 进入同步代码块

判断此头结点的hash值,是否大于零,大于零则说明是链表的头结点在链表中寻找,如果有相同hash值并且key相同,就直接覆盖,返回旧值 结束如果没有则就直接放置在链表的尾部

此头节点的Hash值小于零,则说明此节点是红黑二叉树的根节点

调用树的添加元素方法,判断当前数组是否要转变为红黑树

3、get 方法

首先获取到Key的hash值,

然后找到对应的数组下标处的元素

如果次元素是我们要找的,直接返回,

如果次元素是null 返回null

如果Key的值< 0 ,说明是红黑树,

4、扩容:tryPresize()

容后数组容量为原来的 2 倍。

ConcurrentHashMap的原理分析 - Java技术债务

扩容是的线程安全

  1. 复制槽节点时,会把原数组的当前槽节点锁住,避免并发产生的线程安全问题;
  2. 拷贝成功之后,会把原数组的槽点设置成转移节点,这样如果有数据需要 put 到该节点时,发现该槽点是转移节点,帮助扩容,直到扩容成功之后,才会重新 put,可以参考 put 方法中的 helpTransfer 方法;
  3. 等扩容拷贝都完成之后,直接把新数组的值赋值给数组容器
完
  • 本文作者:Java技术债务
  • 原文链接: https://cuizb.top/myblog/article/1638372347
  • 版权声明: 本博客所有文章除特别声明外,均采用 CC BY 3.0 CN协议进行许可。转载请署名作者且注明文章出处。
阅读全文
Java技术债务

Java技术债务

Java技术债务
Java技术债务
热门文章
  1. ClickHouse使用过程中的一些查询优化(六)2003
  2. MySQL数据库被攻击,被删库勒索,逼迫我使出洪荒之力进行恢复数据764
  3. MySQL主从同步原理458
  4. 线程池的理解以及使用414
  5. Spring Cloud Gateway整合nacos实战(三)409
分类
  • Java
    30篇
  • 设计模式
    27篇
  • 数据库
    20篇
  • Spring
    18篇
  • MySQL
    13篇
  • ClickHouse
    11篇
  • Kubernetes
    10篇
  • Redis
    9篇
  • Docker
    8篇
  • SpringBoot
    7篇
  • JVM
    6篇
  • Linux
    5篇
  • Spring Cloud
    5篇
  • 多线程
    5篇
  • Netty
    4篇
  • Kafka
    4篇
  • 面经
    4篇
  • Nginx
    3篇
  • JUC
    3篇
  • 随笔
    2篇
  • 分布式
    1篇
  • MyBatis
    1篇
  • 报错合集
    1篇
  • 生活记录
    1篇
  • 源码
    1篇
  • 性能优化
    1篇

最新评论

  • MySQL数据库被攻击,被删库勒索,逼迫我使出洪荒之力进行恢复数据2022-05-06
    Java技术债务:@capture 一起探讨学习,服务器被黑很正常,及时做好备份以及做好防护
  • MySQL数据库被攻击,被删库勒索,逼迫我使出洪荒之力进行恢复数据2022-04-13
    capture:我的刚上线两天,网站里就两篇文章也被攻击了,纳闷
  • Java常用集合List、Map、Set介绍以及一些面试问题2022-01-18
    Java技术债务:HashSet和TreeSet 相同点:数据不能重复 不同点: 1、底层存储结构不同; HashSet底层使用HashMap哈希表存储 TreeSet底层使用TreeMap树结构存储 2、唯一性方式不同 HashSet底层使用hashcode()和equal()方法判断 TreeSet底层使用Comparable接口的compareTo判断的 3、HashSet无序,TreeSet有序
  • undefined2021-12-14
    Java技术债务:如果不指定线程池,CompletableFuture会默认使用ForkJoin线程池,如果同一时间出现大量请求的话,会出现线程等待问题,建议使用自定义线程池。。。
  • undefined2021-12-02
    you:很好,对于小白相当不错了,谢谢
  • CSDN
  • 博客园
  • 程序猿DD
  • 纯洁的微笑
  • spring4all
  • 廖雪峰的官方网站
  • 猿天地
  • 泥瓦匠BYSocket
  • crossoverJie
  • 张先森个人博客
  • 越加网

© 2021-2022 Java技术债务 - Java技术债务 版权所有
总访问量 0 次 您是本文第 0 位童鞋
豫ICP备2021034516号
Java技术债务 豫公网安备 51011402000164号

微信公众号

Java技术债务
Java技术债务

专注于Spring,SpringBoot等后端技术探索

以及MySql数据库开发和Netty等后端流行框架学习

日志
分类
标签
RSS

有不足之处也希望各位前辈指出