首页 > 其他分享 >ConCurrentHashMap在1.7和1.8区别

ConCurrentHashMap在1.7和1.8区别

时间:2023-06-23 12:55:18浏览次数:32  
标签:ConCurrentHashMap 1.7 CAS 1.8 线程 数组 put table segment

ConCurrentHashMap 1.8 相比 1.7的话,主要改变为:

  • 去除 Segment + HashEntry + Unsafe 的实现,
    改为 Synchronized + CAS + Node + Unsafe 的实现
    其实 Node 和 HashEntry 的内容一样,但是HashEntry是一个内部类。
    用 Synchronized + CAS 代替 Segment ,这样锁的粒度更小了,并且不是每次都要加锁了,CAS尝试失败了在加锁。
  • put()方法中 初始化数组大小时,1.8不用加锁,因为用了个 sizeCtl 变量,将这个变量置为-1,就表明table正在初始化。

下面简单介绍下主要的几个方法的一些区别:

1. put() 方法

JDK1.7中的实现:

ConCurrentHashMap 和 HashMap 的put()方法实现基本类似,所以主要讲一下为了实现并发性,ConCurrentHashMap 1.7 有了什么改变

  • 需要定位 2 次 (segments[i],segment中的table[i])
    由于引入segment的概念,所以需要
    1. 先通过key的 rehash值的高位segments数组大小-1 相与得到在 segments中的位置
    2. 然后在通过 key的rehash值table数组大小-1 相与得到在table中的位置
  • 没获取到 segment锁的线程,没有权力进行put操作,不是像HashTable一样去挂起等待,而是会去做一下put操作前的准备:
    1. table[i]的位置(你的值要put到哪个桶中)
    2. 通过首节点first遍历链表找有没有相同key
    3. 在进行1、2的期间还不断自旋获取锁,超过 64次 线程挂起!

JDK1.8中的实现:

  • 先拿到根据

    rehash值
    

    定位,拿到table[i]的

    首节点first
    

    ,然后:

    1. 如果为 null ,通过 CAS 的方式把 value put进去
    2. 如果 非null ,并且 first.hash == -1 ,说明其他线程在扩容,参与一起扩容
    3. 如果 非null ,并且 first.hash != -1 ,Synchronized锁住 first节点,判断是链表还是红黑树,遍历插入。

2. get() 方法

JDK1.7中的实现:

  • 由于变量 value 是由 volatile 修饰的,java内存模型中的 happen before 规则保证了 对于 volatile 修饰的变量始终是 写操作 先于 读操作 的,并且还有 volatile 的 内存可见性 保证修改完的数据可以马上更新到主存中,所以能保证在并发情况下,读出来的数据是最新的数据。
  • 如果get()到的是null值才去加锁。

JDK1.8中的实现:

  • 和 JDK1.7类似

3. resize() 方法

JDK1.7中的实现:

  • 跟HashMap的 resize() 没太大区别,都是在 put() 元素时去做的扩容,所以在1.7中的实现是获得了锁之后,在单线程中去做扩容(1.new个2倍数组 2.遍历old数组节点搬去新数组)。

JDK1.8中的实现:

  • jdk1.8的扩容支持并发迁移节点,从old数组的尾部开始,如果该桶被其他线程处理过了,就创建一个 ForwardingNode 放到该桶的首节点,hash值为-1,其他线程判断hash值为-1后就知道该桶被处理过了。

4. 计算size

JDK1.7中的实现:

    1. 先采用不加锁的方式,计算两次,如果两次结果一样,说明是正确的,返回。
    1. 如果两次结果不一样,则把所有 segment 锁住,重新计算所有 segment的 Count 的和

JDK1.8中的实现:

由于没有segment的概念,所以只需要用一个 baseCount 变量来记录ConcurrentHashMap 当前 节点的个数

      1. 先尝试通过CAS 修改 baseCount
      1. 如果多线程竞争激烈,某些线程CAS失败,那就CAS尝试将 CELLSBUSY 置1,成功则可以把 baseCount变化的次数 暂存到一个数组 counterCells 里,后续数组 counterCells 的值会加到 baseCount 中。
      1. 如果 CELLSBUSY 置1失败又会反复进行CASbaseCount 和 CAScounterCells数组

标签:ConCurrentHashMap,1.7,CAS,1.8,线程,数组,put,table,segment
From: https://www.cnblogs.com/javaxubo/p/17499016.html

相关文章

  • ConcurrentHashMap的使用场景
    一、并发容器ConcurrentHashMapHashMap是我们用得非常频繁的一个集合,但是它是线程不安全的。并且在多线程环境下,put操作是有可能产生死循环,不过在JDK1.8的版本中更换了数据插入的顺序,已经解决了这个问题。为了解决该问题,提供了Hashtable和Collections.synchronizedMap(hashMap)......
  • ConcurrentHashMap使用案例(单词数量统计)
    前言目标:实现单词数量统计过程:首先使用26个英文字母,每个字母200个,将26200个字母打乱顺序存入26个txt文件中。使用26个线程,每个线程统计一个txt文件的200个字母。26个线程同时操作这一个Map集合。最终想要得到的结果为:a:200(a被统计了200次),b:200(b被统计了200次)……z:200(z被统计200......
  • Subversion 1.8.9 ( SVN Client ) 安装最新版本的svn客户端 - svn 账户 密码
    http://www.fulingjiang.cn/linux/62.htmlForCentOS7Users: 1.[WandiscoSVN]2.name=WandiscoSVNRepo3.baseurl=http://opensource.wandisco.com/centos/5/svn-1.8/RPMS/$basearch/4.enabled=15.gpgcheck=06.yumcleanall7.......
  • Centos安装JDK1.8
    1、卸载centos原本自带的openjdk运行命令如下:rpm-qa|grepjava 编辑2、然后通过rpm-e--nodeps后面跟系统自带的jdk名这个命令来删除系统自带的jdk例如:rpm-e--nodepsjava-1.8.0-openjdk-1.8.0.102-4.b14.el7.x86_64rpm-e--nodepsjava-1.8......
  • HashMap 、LinkedHashMap 、 Hashtable 、ConcurrentHashMap的使用区别和Collections
    LinkedHashMapLinkedHashMap的使用publicstaticvoidmain(String[]args){ LinkedHashMap<String,Integer>map=newLinkedHashMap<>(); //添加元素 Integerput1=map.put("大文",25); Integerput2=map.put("小文",26); Integer......
  • 大厂技术总监总结的Android Framework开发笔记火了!知乎已1.7k赞!不吃透都对不起他
    为什么要学AndroidFramework?想要成为一名优秀的Android开发,就需要有一个完备的知识体系,AndroidFramework的知识是很重要的一个组成部分,他广泛的应用在各个领域。像掉帧监控,函数插装,慢函数检测,ANR监控,启动监控,都需要对Framework有比较深入的了解。只有这样才能知道怎么去做监......
  • 为什么jdk1.7的HashMap会产生死循环?
    前言JDK1.7中的HashMap在多线程情况下扩容可能会导致死循环。本文就这个问题进行讲解。扩容死循环这里回顾一下HashMap1.7扩容的过程,在扩容过程中,单链表的表现,相关的代码如下:Jdk1.7:voidresize(intnewCapacity){Entry[]oldTable=table;intoldCapacity=......
  • CentOs7安装部署Sonar环境(JDK1.8+MySql5.7+sonarqube7.8)
    sonarqube安装前环境准备JDK1.8、MySql5.7。一、JDK安装1、下载jdk #打开下面的网址,选择jdk-8u371-linux-x64.tar.gz进行下载(8u371版本可能会有区别,但是没有影响) http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html2、......
  • CentOs7安装部署Sonar环境(JDK1.8+MySql5.7+sonarqube7.8)
    sonarqube安装前环境准备JDK1.8、MySql5.7。一、JDK安装1、下载jdk#打开下面的网址,选择jdk-8u371-linux-x64.tar.gz进行下载(8u371版本可能会有区别,但是没有影响)http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html2、安装jdk#创建......
  • Java低代码开发工具:jvs-rules 2.1.8 新版本功能清单
    规则引擎用于管理和执行业务规则。它提供了一个中央化的机制来定义、管理和执行业务规则,以便根据特定条件自动化决策和行为。规则引擎的核心概念是规则。规则由条件和动作组成。条件定义了规则适用的特定情况或规则触发的条件,而动作定义了规则满足时要执行的操作或行为。jvs-rules......