不安全代码
package com.my.list;
import java.util.HashMap;
public class HashMapNoSecurity {
public static HashMap<String,String> hashMap = new HashMap<>();
public static void main(String[] args) throws InterruptedException {
//两个线程去放数值
//线程一
Thread t1 = new Thread(){
@Override
public void run() {
for(int i=0;i<50;i++){
hashMap.put(String.valueOf(i),String.valueOf(i));
}
}
};
//线程二
Thread t2 = new Thread(){
@Override
public void run() {
for(int i=50;i<100;i++){
hashMap.put(String.valueOf(i),String.valueOf(i));
}
}
};
//线程三
Thread t3 = new Thread(){
@Override
public void run() {
for(int i=100;i<150;i++){
hashMap.put(String.valueOf(i),String.valueOf(i));
}
}
};
t1.start();
t2.start();
t3.start();
//主线程休眠
Thread.currentThread().sleep(2000);
//比较可以值
for(int i=0;i<150;i++){
//如果key value不同,则put过程异常
if(!hashMap.get(String.valueOf(i)).equals(String.valueOf(i))){
System.out.println("error->"+hashMap.get(i));
}
}
}
}
执行了很多次后,有报错
Exception in thread "main" java.lang.NullPointerException
at com.my.list.HashMapNoSecurity.main(HashMapNoSecurity.java:51)
大致出错的逻辑是
源代码HashMap 1.7里面
/**
* Transfers all entries from current table to newTable.
*/
void transfer(Entry[] newTable, boolean rehash) {
int newCapacity = newTable.length;
for (Entry<K,V> e : table) {
while(null != e) {
Entry<K,V> next = e.next;
if (rehash) {
e.hash = null == e.key ? 0 : hash(e.key);
}
int i = indexFor(e.hash, newCapacity);
e.next = newTable[i];
newTable[i] = e;
e = next;
}
}
}
newTable[i] = e;行,
当2个线程去扩容的时候,第一个线程在newTable[i] = e;阻塞住了,等待cpu资源调用,第二个线程扩容完毕,导致newTable表重新更新到主内存中,基于1.7是头插法,导致有循环引用的功能。