• 并发容器之ConcurrentMap


    一、concurentMap

    1、数据结构,分段数组segment不扩容,里面的table扩容,每次翻倍,table中放的是entry链表的头地址;

     2、初始化

     

     segment和table的长度都是2的幂次方,方便位运算,位运算扩容之后可以保证原先的元素排列不变;

    用于定位元素所在segmentsegmentShift表示偏移位数通过前面的int类型的位的描述我们可以得知,int类型的数字在变大的过程中,低位总是比高位先填满的,为保证元素在segment级别分布的尽量均匀,计算元素所在segment时,总是取hash值的高位进行计算。segmentMask作用就是为了利用位运算中取模的操作:l a % (Math.pow(2,n)) 等价于 a&( Math.pow(2,n)-1)

    3、get、put方法;

    实现原理都是先通过hashcode位运算,找出在segment中的位置,key的hashcode再散列,找出在table中的位置,再确定equals是否相等,判定是否重复;

    所以equals和hashCode方法要一起重写;

     put时候是加锁的,所以线程安全;

    get时候不加锁,所以是弱一致性;如何保证线程安全,修饰value时候用了volatile;

    4、ConcurrentHashMap允许多个修改操作并发进行,其关键在于使用了锁分离技术。它使用了多个锁来控制对hash表的不同部分进行的修改。内部使用段(Segment)来表示这些不同的部分,每个段其实就是一个小的hash table,只要多个修改操作发生在不同的段上,它们就可以并发进行

    二、jdk1.8之后concurrentMap

     值少用链表结构简单,多的时候用红黑树,查询时间复复杂度低logn,但是结构实现复杂;

     1.7相比的重大变化

    1、 取消了segment数组,直接用table保存数据,锁的粒度更小,减少并发冲突的概率。

    2、 存储数据时采用了链表+红黑树的形式,纯链表的形式时间复杂度为O(n),红黑树则为Ologn),性能提升很大。什么时候链表转红黑树?当key值相等的元素形成的链表中元素个数超过8个的时候。非树化是6个时候

     

    主要数据结构和关键变量

     

    Node类存放实际的keyvalue值。

     

    sizeCtl:

     

    负数:表示进行初始化或者扩容,-1表示正在初始化,-N,表示有N-1个线程正在进行扩容

     

    正数:0 表示还没有被初始化,>0的数,初始化或者是下一次进行扩容的阈值

     

    TreeNode 用在红黑树,表示树的节点, TreeBin是实际放在table数组中的,代表了这个红黑树的根

    初始化做了什么事?

    只是给成员变量赋值,put时进行实际数组的填充

    getput操作中,是如何快速定位元素放在哪个位置的?

     

     

    get()方法

     

    put()方法

    数组的实际初始化

     

     

     

    扩容操作

    transfer()方法进行实际的扩容操作,table大小也是翻倍的形式,有一个并发扩容的机制,put时候发现在扩容会帮助扩容。

    size方法

    估计的大概数量,不是精确数量

    一致性

    弱一致

     

  • 相关阅读:
    从零开始学Bootstrap
    CSS VS JS动画,哪个更快
    css定位(positon)
    json
    使用 CSS3 绘制 Hello Kitty
    后台找到repeater里面的div并添加客户端点击事件
    dropDownList之"请选择",同时设置默认选项
    asp.net 后台对话框,确认跳转
    后台生成textbox并设置多行属性,自动换行
    asp.net多图片上传同时保存对每张图片的描述
  • 原文地址:https://www.cnblogs.com/wmqiang/p/11691450.html
Copyright © 2020-2023  润新知