ConcurrentHashMap

Posted lankerenf3039

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConcurrentHashMap相关的知识,希望对你有一定的参考价值。

负载因子:元素个数>=桶个数*负载因子,则触发扩容。默认桶个数16,默认负载因子0.75。
HashMap的容量是2的幂次可以把哈希取模的操作变成位运算以加快运算速度,当length是2的幂次时,a%length <=> a&(length-1) (比如101101%1000 <=>101101&111 = 101)。

1.7 HashMap
哈希表,头插法
2个线程put,同时扩容会出现链表成环

1.7 ConcurrentHashMap
分段锁(段内扩容,重新hash),ReentrantLock

1.8 HashMap
哈希表,当链表达到一定长度则转化为红黑树
尾插法,避免2个线程put扩容链表成环

---------------------------------------------
1.8 ConcurrentHashMap
get操作不加锁,因为Node的val和next用volatile修饰,其它线程修改val或者新增结点修改next对get线程可见。
table数组用volatile修饰是保证扩容时的可见性(并发扩容)。

get方法
根据key计算hashcode找到对应的桶,如果在桶上(hashcode=桶结点的hashcode)则直接返回val。
如果桶结点是树的根节点,则按照树的方式找,
如果桶结点是链表首结点,则按照链表的方式找。
遍历时读取volatile修饰的next,找到时返回volatile修饰的val。

put方法
根据key计算hashcode
循环以下
如果table为空则初始化
根据hashcode找到桶,如果桶结点为空,则cas写入新的桶结点和值(原值null),退出循环
如果结点hashcode为MOVED(-1),说明正在扩容,则本线程帮助扩容
如果以上都不满足,则给桶加synchronized锁,尾插法写入数据

 

扩容
增加了ForwardingNode表示扩容中的结点,让其它写线程也来帮助扩容。
sizeCtl:0表示还未初始化,-1表示正在初始化,-N表示N-1个线程正在扩容,+N表示下一次扩容的大小。
扩容步骤
新建一个原来2倍的数组,把原数组的元素插入到新数组。

以上是关于ConcurrentHashMap的主要内容,如果未能解决你的问题,请参考以下文章