Java HashMap & Concurrent Hash Map
为啥拉链用尾插不用头插?
- jdk 1.7 用的头插,但头插的问题就是resize:因为hash取值后放置是从后往前(头插,逆序链表方向)的,但是在resize时会重计算hash,此时是顺序遍历方向,那么就可能出现一开始A头插在B前,rehash时B
后进行rehash导致B
头插在A前。这样AB的顺序resize后就不同了。这样就会使得多线程时对引用的指向调整有问题,有可能造成循环链表了。尾插法的顺序和rehash时遍历的顺序一致自然就不会有这个问题。
- jdk 1.7 用的头插,但头插的问题就是resize:因为hash取值后放置是从后往前(头插,逆序链表方向)的,但是在resize时会重计算hash,此时是顺序遍历方向,那么就可能出现一开始A头插在B前,rehash时B
Collections.synchronizedMap
内部维护了一个 map 用来引用需要改造的map,通过加 mutex 排他锁的形式来对map进行各种操作。其实就是全部用 synchronized 包裹起来。
fail-safe & fail-fast
hashtable 使用的是 fail-safe 机制,该机制会在进入遍历前,记录当前集合的内容,然后遍历记录的集合内容,不关心集合在此期间的意外修改情况。类似得还有 copyOnWriteList
fail-fast: 每次集合变动会使得 modCount 跟着变动,而使用 next 遍历前会检查这个 modCount 是否是期望值。
Concurrent Hash Map
- 1.7 版本的分段方式 segment
1 | // 先定位 segment,对 segment后进行put操作 |
- 1.8 版本的 CAS + synchronized
1 | final V putVal(K key, V value, boolean onlyIfAbsent) { |
红黑树
定义
根节点叶子节点都是黑色 且 叶子都是 NIL 节点
路径上不能有两个连续的红色节点
从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点
带来的效益:最长路径不会超过最短路径的两倍
变色 & 旋转
基础:红黑树的插入节点都是红色的
变色
- 红变黑或者黑变红,变化过程可能会发生连锁反应
旋转
- 逆时针旋转,即父节点抢了右子节点的左儿子作为自己的右儿子,然后自己去认右子节点为爹。如图
- 顺时针旋转,上面的左右互换即可。即父节点抢了左子节点的右儿子作为自己的左儿子,然后自己去认右子节点为爹。
应用
- Post title:Java HashMap & Concurrent Hash Map
- Post author:ReZero
- Create time:2020-08-09 10:00:00
- Post link:https://rezeros.github.io/2020/08/09/HashMap/
- Copyright Notice:All articles in this blog are licensed under BY-NC-SA unless stating additionally.
Comments