多线程访问HashpMap产生死锁原因
来源:互联网 发布:知乎wifi刷不出来图片 编辑:程序博客网 时间:2024/06/08 07:08
通过源码知道:HashMap的基本数据结构是Entry[] table。每个entry=table[i]都有next属性,它其实只指向和entry有相同hash值的下一个对象,也就是同一个桶中的下一个数据。
HashMap这个数据结构不是线程安全的,几乎所有人都知道。当我们采用多线程进行读写的时候必然会存在线程同步的问题。那怎么会产生死锁呢?我来贴下源代码。
void resize(int newCapacity) { Entry[] oldTable = table; int oldCapacity = oldTable.length; if (oldCapacity == MAXIMUM_CAPACITY) { threshold = Integer.MAX_VALUE; return; } Entry[] newTable = new Entry[newCapacity]; transfer(newTable); table = newTable; threshold = (int)(newCapacity * loadFactor); } /** * Transfers all entries from current table to newTable. */ void transfer(Entry[] newTable) { Entry[] src = table; int newCapacity = newTable.length; for (int j = 0; j < src.length; j++) { Entry<K,V> e = src[j]; if (e != null) { src[j] = null; do { Entry<K,V> next = e.next; int i = indexFor(e.hash, newCapacity); e.next = newTable[i]; newTable[i] = e; e = next; } while (e != null); } } }
resize函数是发生在容量不够的情况下的。当申请完了新的内存空间后,我们要把原来的内存空间中的数据转移到新内存空间中去。也就是transfer函数。
假设现在有三个线程:T1,T2,T3;在老数组中的第一个数据也就是e引用的对象,我们称它为A,在新数组中的头两个数据分别为B和C,B.next=C。
线程T1运行到e.next=newTable[i]时线程T2运行到next=e.next;然后线程t1去继续
运行,会产生什么效果呢?A.next=B,B.next=C。e指向的对象是B,newTable[i]=A。然后继续运行,e.next=newTable[i],也就是B.next=A;同时A.next=B,继续运行newTable[i] = e,e = next;如果没有其它线程捣乱的话,那么此时e应该是C啊,可惜只是如果,如果有第三个线程T3在线程T1执行e.next = newTable[i]的时候去执行next = e.next;那么就中途改变了next的值,本来是保存C的,但是现在成了A了。总结下现在的情况:e引用A,nextTable[i]引用B,A.next=B,B.next=A。现在明白了吧。会一直这么死锁下去的。
- 多线程访问HashpMap产生死锁原因
- 多线程死锁的产生原因及避免
- Java多线程产生死锁的原因和解决方法
- 产生死锁的原因
- 死锁产生的原因
- 产生死锁的原因
- 产生死锁的原因
- 死锁产生的原因
- 多线程四,死锁产生的原因和死锁的例子(毕向东老师)
- 死锁和产生的原因
- 进程产生死锁的原因
- 万向节死锁产生的原因
- 死锁及死锁产生原因条件
- Java多线程探究-死锁原因
- 死锁,死锁产生的原因,产生死锁的必要条件和解决死锁的方法
- JAVA 死锁,死锁产生的原因,产生死锁的必要条件和解决死锁的方法
- SQL Server死锁产生原因及解决办法
- SQL Server死锁产生原因及解决办法
- OpenGL的回调函数
- 第四章实验作业
- 一些我推荐的和想上的网络课程
- C/C++编译时的内存分配
- 第四章作业
- 多线程访问HashpMap产生死锁原因
- MFC API——》Create 、CreateEx
- Android浏览器的插件原理
- Maven学习(一)- 环境搭建
- 如何把单子做大
- Android开发-02-自己常用的一个get和post方式提交类的封装
- NYOJ 248 BUYING FEED
- 第五周作业
- 第五周作业