zoukankan      html  css  js  c++  java
  • 并发容器之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方法

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

    一致性

    弱一致

     

  • 相关阅读:
    收藏的博客
    MVC 之 System.Web.Optimization找不到引用
    SQL Server 之 附加数据库出现“ 拒绝访问 ”
    Android Studio 之 环境搭建
    PD 之 连接数据库并导出数据及生成PDM文件
    Windows 之 可以Ping通服务器但无法使用服务器连接的共享打印机
    JQuery 之 在数据加载完成后才自动执行函数
    JavaScript 之 动态加载JS代码或JS文件
    JQuery 之 动态加载JS或JS文件
    JavaScript 之 解码类似eval(function(p,a,c,k,e,d){}))的JavaScript代码
  • 原文地址:https://www.cnblogs.com/wmqiang/p/11691450.html
Copyright © 2011-2022 走看看