并发容器ConcorrentHashMap与Hash

Hash是压缩映射

Hash冲突的处理方式

开放寻址发ThreadLocal

链地址法CorrentHashMap

再哈希

 

常用Hash函数

志杰取余法,乘法取整法,平方取中法

MD5 SHA-1等虽然是加密算法,但其实是摘要算法,不可逆,不可能从摘要反推到明文,彩虹表可以解析,可以加盐后加密,也可以位运算后加密,或者加密后位运算异或

 

1.7HashMap 死锁,1..7之前头插法,多线程同时扩容,一个线程执行一半被挂起,另一个线程扩容完之后,扩容相同的元素,链表的next与prev产生了一个循环链表头插死循环,get(不存在元素的时候),循环链表造成死循环

concrrentHashMap.putisAbsent()不存在则插入

concrrentHashMap1.7与1.8锁机制和数据结构有不同,

1.7  segment 用的 reetrantLock,2的平方数,锁住的桶,无参构造器还是调用的带参数的内部有参构造,缺省并发大小16,初始化,初始化桶16个segment个,根据加载因子算的,实例化segment[0],segment不可扩容,扩容的是segment下的table

get方法,key拿到hash值,jackwang的hash算法,定位segment,定位table链表,get不加所,value是volitail

 

1.7concrrentHashMap

取模a%(2`n) = a&(2`n-1),put方法自旋获取锁,自旋一定次数没拿到,则阻塞拿锁,put完释放锁,头插法,指针泛化

size()方法是线程安全的可能会影响性能,对segment加锁再累加计算,containValue也会加锁,影响性能,

是弱一致的,get并没有加锁,返回的可能是过时的数据

 

1.8concrrentHashMap

没有segment(就是个显示可重入锁ReetrantLock),  cas+syc锁实现, 数组链表红黑树 ,HashEntry改为了Node似乎一样,TreeNode继承Node,有读写锁机制,当节点数大于8转换为红黑树,当节点小于6重新转化为链表,TreeBin是红黑树的根节点,ForwordingNode扩容时候用,扩容时标识节点已被移动,sizeClt控制table初始化和扩容操作,-1正在初始化,-N当前有多少个线程正在扩容,0是默认值表明table没有初始化,正数表示当前table的初始化大小,tabAt()  casTabAt()  setTabAt(),硬件级别的原子操作

new concrrentHashMap()只是简单的赋值了成员变量,out才实例化table,和1.7不同,1.7做了一系列的初始化操作,1:28

put方法初始化table,初始化大小是2的乘方

get方法,得到hash值,判断如果是树,就用树的方式去找,如果是链表就用链表的方式去找

put计算hash值,死循环进行插入,key和value都不是null,检查table是否是空,是空则进行初始化操作,多线程初始化table, 保证只有一个线程在初始化,判断flag,如果有线程正在初始化进行yield,cas操作保证只有一个线程在初始化,扩容0.75倍位运算,-无符号右移两位,判断table头有没有值,有值则cas操作放入值,插入时候会看table是否正在扩容,如果横在扩容则帮助其他线程进行扩容,将table的桶分给其他线程,多个线程之间不操作相同的数据,避免造成1.7get元素之间形成循环链表时候死循环的问题,扩容完之后在尝试向链表或者红黑树中放入数据,尾插发,放数据时候采用了synchronized锁,锁住的是table的表头,插入时候会看插入后的元素个数是否过了树的临界点,过了的话将链表转换为红黑树,map元素累加(cas一次操作basecount,并发累加countCell记录失败的次数),判断是否需要扩容

remove 和put过程很相似,只不过插入变成了删除,最后map元素个数减1(cas一次操作basecount,并发累加countCell记录失败的次数,例如一个线程在put一个线程在remove),6千多行代码

put和get都会帮助扩容,helperTransfer,两倍大小的数组,将原来数组的数据移过来,不同的线程步长不同,补货重复扩容相同的链表或者树,

当对table节点扩容完成标识为forwordingNode,别的线程就不会再对此线程进行扩容,将新table数组的大小编程当前0.75倍

会帮助一起扩容,避免冲突,采用了步长来分别扩容,分成了多个小任务,每个线程负责其中一个小部分

breeifyBin转换为红黑树,fh的hash值节点判断

size方法取总数量时候basecount+countCell ,实际上还是不太准,只是提高了性能,

 

hashTable的方法都加了sychornized关键字,锁了整个对象,强一直性效率低,concrrentHashMap里了cas与sychornized与分段锁,提高了效率

数据结构,put get 怎么实现,sizeCtl控制了初始化大小与扩容大小,Node继承自Enry用来存储数据15

concurrentHashMap的数据结构,put与get怎么实现的,treeNode封装了我们的节点,treeBin封装了treeNode并提供了一些锁的控制

1.7concurrentHashMap并发度是什么,同时更新map并扩容并不产生锁竞争的最大线程数的默认为16,可以在构造函数中设置,会自动调整为2的正方 1.8中并发度没有实际意义,如果并发度不够,则将初始容量提升至并发度大小

数组查找快,扩容麻烦,链表添加快,查找慢

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章