hashmap多线程操作会造成链表的循环,这个已经被各种博客的讲烂了。大家都知道是put过程中的resize方法在调用transfer方法的时候导致的死锁,故在此不详述。
今天在看《java高并发程序设计》的时候,书中提到“但是这个(hashmap)死循环的问题在jdk8中已经不存在了。由于jdk8对hashmap的内部上线了大规模的调整,因此规避了这个问题”
那么问题来了- -。jdk8是如何规避这个问题的呢,百度无果,只好自己打开源码看看了。比如知名博客《Java8系列之重新认识HashMap》,在讲述resize的时候还是用了jdk7的代码。。。
打开源码 搜索transfer。。。我的天 居然没有。。。
那搜索resize吧。找到核心代码如下(忽略红黑树部分,仅考虑链表部分)
// preserve order
Node loHead = null, loTail = null;
Node hiHead = null, hiTail = null;
Node next;
//处理某个hash桶部分
do {
next = e.next;
{//确定在newTable中的位置
if (loTail == null)
loHead = e;
else
loTail.next = e;
loTail = e;
}
else {
if (hiTail == null)
hiHead = e;
else
hiTail.next = e;
hiTail = e;
}
} while ((e = next) != null);
声明两对指针,维护两个连链表
依次在末端添加新的元素。(在多线程操作的情况下,无非是第二个线程重复第一个线程一模一样的操作)
的确没想到这么简单。。。
总结。1.8中hashmap的确不会因为多线程put导致死循环,但是依然有其他的弊端,比如数据丢失等等。因此多线程情况下还是建议使用concurrenthashmap。