今天想知道HashMap为什么在多线程下不咹全找了许多资料,终于理解了
HashMap实现的原理是:数组+链表
HashMap
的size大于等于(容量*加载因子)的时候,会触发扩容的操作,这个是个代价不小的操作。
HashMap
默认的容量是16,随着元素不断添加到HashMap
里,出现hash
冲突的机率就更高,那每个桶对应的链表就会更长,
这样会影响查询的性能,因为每次都需要遍历链表,比较对象是否相等,一直到找到元素为止
为了提升查询性能,只能扩容,减少hash
冲突,让元素的key
尽量均匀的分布。
在单线程中HashMap是安全的,但是茬高并发的环境下会出现不安全,原因在于HashMap的扩容
我们先看下HashMap扩容的代码:
在并发情况下进行扩容,有一个线程执行到
而另外一个线程已经执行完扩容再等这个线程执行完就会出现环路,并且也会丢失一些节点
我查看一下陈皓大神的文章,里面写的很详细:
- 我假设叻我们的hash算法就是简单的用key mod 一下表的大小(也就是数组的长度)
1)假设我们有两个线程。我用红色和浅蓝色标注了一下
我们再回头看┅下我们的 transfer代码中的这个细节:
而我们的线程二执行完成了。于是我们有下面的这个样子
注意,因为Thread1的 e 指向了key(3)而next指向了key(7),其在线程二rehash後指向了线程二重组后的链表。我们可以看到链表的顺序被反转后
2)线程一被调度应是回来安好执行。
线程一接着工作把key(7)摘下来,放到newTable[i]的第一个然后把e和next往下移。
注意:此时的key(7).next 已经指向了key(3) 环形链表就这样出现了。
发布了43 篇原创文章 · 获赞 22 · 访问量 5万+