HashMap多线程不安全问题总结
1个回答
展开全部
1、HashMap的底层数据结构是数组+链表的结构。在插入数据的时候,会先计算数据的hashcode值,再取余放入数组对应下标处。如果发生hash碰撞,则插入当前node的后面,形成一个链表的结构。
2、数组的默认大小是16,默认的扩容因子是0.75,每次达到阈值( size * 0.75)的时候,就会对数组进行扩容,扩容每次都是在现有基础上扩容2倍。
3、在数组长度大于64,并且链表长度大于8的时候,链表会转成红黑树,之所以是需要数组长度大于64,是因为优先要扩容数组大小,减少hash碰撞的次数,提高性能。在红黑树小于7的时候,会转成链表,之所以是要小于7,是避免红黑树和链表之间的频繁转换。
了解到了HashMap的主要特点,再来看HashMap的线程不安全问题:
在线程A、B put的数据发生hash碰撞并且数组里面已经有数据的情况下,两个线程同时获得头结点的next指针,next指针只能指向一条数据,比如有另外一条数据丢失。
在数组扩容的时候,会new一个新的数组出来,再遍历旧的数组,如果从旧数组里面取出来的值非null,会将这个值取出来放到新数组里面,并将旧数组里面的值置为null,而这个时候,旧数组还没有遍历完全,另外一个线程get数据的时候可能获取到的时候就是null。
2、数组的默认大小是16,默认的扩容因子是0.75,每次达到阈值( size * 0.75)的时候,就会对数组进行扩容,扩容每次都是在现有基础上扩容2倍。
3、在数组长度大于64,并且链表长度大于8的时候,链表会转成红黑树,之所以是需要数组长度大于64,是因为优先要扩容数组大小,减少hash碰撞的次数,提高性能。在红黑树小于7的时候,会转成链表,之所以是要小于7,是避免红黑树和链表之间的频繁转换。
了解到了HashMap的主要特点,再来看HashMap的线程不安全问题:
在线程A、B put的数据发生hash碰撞并且数组里面已经有数据的情况下,两个线程同时获得头结点的next指针,next指针只能指向一条数据,比如有另外一条数据丢失。
在数组扩容的时候,会new一个新的数组出来,再遍历旧的数组,如果从旧数组里面取出来的值非null,会将这个值取出来放到新数组里面,并将旧数组里面的值置为null,而这个时候,旧数组还没有遍历完全,另外一个线程get数据的时候可能获取到的时候就是null。
已赞过
已踩过<
评论
收起
你对这个回答的评价是?
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询