美文网首页
聊聊HashMap

聊聊HashMap

作者: jqdywolf | 来源:发表于2018-03-14 11:02 被阅读0次

HashMap

jdk1.7实现版本

数组+链表

  • 引入
    数组+链表。很简单,初始化一个数组,解决冲突的办法就是开链法:将hashCode相同的元素放入链表中。


    image.png
  • 非线程安全
    hashmap是非线程安全的,即hashmap的实现中不涉及同步锁的概念。所以多个线程put或一个线程put一个线程get都会引起同步问题。
  • resize操作
    • 装载因子:hashmap总元素个数/数组长度
    • 在put方法中,如果发现新增元素后,hashmap的装载因子过高(默认是0.75),就会自动触发resize操作。
    • resize操作的步骤:申请两倍大小的数组,将原数组中的链表一次转移到新的数组中。具体操作是修改对象引用,并不是完全new每个链表的每个结点。
    • 上述的转移操作可能会引发死循环问题:多个线程同时put,同时触发resize操作,在转移链表的过程中,引起了引用的回路,造成死循环。可能会把CPU打到100%。
jdk1.8实现版本

数组+链表+红黑树

  • 并不解决线程安全问题,而是提升了get方法的效率。
  • 当一个链表的个数打到某个阈值(默认8)时,就会使用红黑树来代替链表。显然get效率从之前的O(n)->O(logn)。

ConcurrentHashMap

上面说hashmap并不是线程安全的,ConcurrentHashMap就是用来解决线程安全的。

jdk1.7实现版本

数组+segment+链表
同步:segment+ReentrantLock

  • 数据结构


    image.png

如图所示,map由1.7中的两级被分为了三级。首先hashmap中存的是segment数组。每个segment数组中存放一个实体数组,每个数组中是一个链表结构。

  • 如何解决线程安全问题?
    • 每个segment对象继承了ReentrantLock,即对分段进行加锁管理。
    • put操作
      先获取锁:自旋的retryLock,一段时间后再进行阻塞的lock。
      然后再进行写入操作
    • get操作
      并不加锁。get操作使用的共享变量都被声明为valotile,保证了线程可见性,所以可以直接读取。除了需要链表顺序查找,这个设计还是很棒的。
  • 缺点
    • size()得到的结果可能不是特别准
      jdk7对于ConcurrentHashMap size的内部实现:依次对每个segment进行size操作,然后将每个segment的size相加。整个map连续进行两次这样的操作,如果两次的结果相同则返回。否则锁住整张表。
    • 我们发现其实锁的粒度为segment,这个粒度还是有点粗,即修改同一个segment下的两个不同的元素也会被阻塞。如果可以是每个数组元素就很好了。
jdk1.8实现版本

数组+链表+红黑树
同步:CAS+synchronized

目的就是为了提高了1.7效率。
如何提高?

  • 数据结构
    和jdk1.8中的hashmap一样,使用红黑树代替链表。
    取消了segment三层结构,使用和hashmap一样的两层结构。
  • 锁的粒度
    上面我们知道1.7中锁的粒度为segment,而在1.8中取消了segment。锁的粒度变成了每个数组的元素(使用synchronized)。这样引发了一个问题,那么跨数组元素的操作怎么办?比如size操作。
    • 解决办法:将map的size变量设为原子性变量,比如AtomicInteger变量。每次put或remove维护这个变量即可。
  • 具体操作
    • put操作。先使用CAS进行put,如果失败则使用synchronized加锁。
    • get操作。和1.7一样,使用valotile保证效率。
    • size操作。每次put或remove维护一个原子变量即可。

相关文章

  • 聊聊HashMap

    HashMap jdk1.7实现版本 数组+链表 引入数组+链表。很简单,初始化一个数组,解决冲突的办法就是开链法...

  • 聊聊HashMap

    HashMap是Java程序猿平时用的较多的一种数据结构,也经常会在各种面试中被问起。喜欢看JDK源码的同学肯定会...

  • 聊聊HashMap原理

    能力要进阶,必然就要多了解了解原理。看了一些Java的数据结构,简单的总结下HashMap原理。所谓map就是一个...

  • 简单聊聊 HashMap

    哈喽,今天我们来聊聊HashMap。 HashMap相信大家在平时开发的时候也会经常用到,它是基于哈希表的 Map...

  • 聊聊java中的哪些Map:(六)ConcurrentHashM

    [toc] 在聊完HashTable和HashMap的区别之后,自然该到了聊聊ConcurrentHashMap的...

  • ConcurrentHashMap锁机制进化的考量

    前言 又是有一段时间没写过Java相关的东西了。本来是想返璞归真一把,聊聊HashMap的,但HashMap的内容...

  • HashMap原理介绍

    今天咋来聊聊hashMap的原理。hashMap是使用频率最高的集合对象之一了,说到集合框架就不得不先来看一幅图。...

  • 聊聊HashMap、ConcurrentHashMap和Hash

    1、HashMap1.1、了解HashMap首先了解以下几个参数:①capacity 容量 默认是static f...

  • Java源码解读 --- ArrayList

    上次说到HashMap的源码,这次来聊聊ArrayList的源码。 ArrayList,顾名思义,底层是用Arra...

  • 聊聊java中的哪些Map:(二)HashMap中的TreeNo

    [toc]本文是上一篇聊聊java中的哪些Map:(一)HashMap(1.8)源码分析中对于treeNode的补...

网友评论

      本文标题:聊聊HashMap

      本文链接:https://www.haomeiwen.com/subject/ipbzfftx.html