JDK1.7中HashMap的死循环问题及解决方案
作者:jacheut
这篇文章主要为大家介绍了JDK1.7中HashMap的死循环问题及解决方案,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
hashMap在多线程环境下的表现
- 在jdk1.7中多线程put时可能会导致get无限循环,具体表现为CPU使用率100%;
该方法实现的机制就是将每个链表转化到新链表,并且链表中的位置发生反转,而这在多线程情况下是很容易造成链表回路,从而发生 get() 死循环。所以只要保证建新链时还是按照原来的顺序的话就不会产生循环(JDK 8 的改进)。即在jdk1.7是采用的头插法,在jdk1.8使用了尾插法解决。
HashMap死循环只发生在JDK1.7版本中,主要原因是JDK1.7中的HashMap,在头插法 加 链表 加 多线程并发 加 扩容这几个情形累加到一起就会形成死循环。多线程环境下建议采用ConcurrentHashMap替代。
- 多线程put时可能导致元素丢失 原因:当多个线程同时执行addEntry(hash,key ,value,i)时,如果产生哈希碰撞,导致两个线程得到同样的bucketIndex去存储,就可能会发生元素覆盖丢失的情况
Hashmap中的链表大小超过八个时会自动转化为红黑树,当删除小于六时重新变为链表,为啥呢?
根据泊松分布,在负载因子默认为0.75的时候,单个hash槽内元素个数为8的概率小于百万分之一,所以将7作为一个分水岭,等于7的时候不转换,大于等于8的时候才进行转换,小于等于6的时候就化为链表。 避免树和链表的频繁转换
从时间复杂度分析,树的查询时间复杂度是logn,所于大于等于8使用红黑树。
Collections.synchronizedMap是怎么实现线程安全的
在SynchronizedMap内部维护了一个普通对象Map,还有排斥锁mutex,如图
我们在调用这个方法的时候就需要传入一个Map,可以看到有两个构造器,如果你传入了mutex参数,则将对象排斥锁赋值为传入的对象。
如果没有,则将对象排斥锁赋值为this,即调用synchronizedMap的对象,就是上面的Map。
创建出synchronizedMap之后,再操作map的时候,就会对方法上锁。
以上就是JDK1.7中HashMap的死循环问题及解决方案的详细内容,更多关于JDK1.7 HashMap死循环解决的资料请关注脚本之家其它相关文章!