2.8.3 并发下诡异的HashMap

package 第二章.并发下诡异的HashMap;

import org.junit.Test;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
* Created by zzq on 2018/1/19.
*/
public class HashMapMultiThread {
static HashMap<String, String> map = new HashMap<String, String>();
static AtomicInteger integer=new AtomicInteger(0);
public static class AddThread extends Thread {
int start = 0;

public AddThread(int start) {
this.start = start;
}

@Override
public void run() {
for (int i = start; i < 100000; i += 2) {
String put = map.put(Integer.toString(i), Integer.toString(i));
// System.out.println(map.size());
}
}
}
public static void main(String args[]) throws InterruptedException {
Thread thread1 = new Thread(new HashMapMultiThread.AddThread(0));
Thread thread2 = new Thread(new HashMapMultiThread.AddThread(1));
thread1.start();
thread2.start();
thread1.join();
thread2.join();
thread2.join();
thread2.join();
int a=0;
for (String i:map.keySet()){
if(!i.equals(map.get(i))){
// System.out.println(i);
a++;
}
}
System.out.println(map.size());
System.out.println(a);
}
@Test
public void aaa(){
System.out.println(8 & 32);
}
}


1.实例中我们可以看出1.8为例:(2个线程得到的size 不一定是2个线程数量之和)

每次添加之前,会执行 int i = indexFor(hash, table.length); 获取table的下标值,
而 indexFor这个方法中(下面为源码)

static int indexFor(int h, int length) {
// assert Integer.bitCount(length) == 1 : "length must be a non-zero power of 2";
return h & (length-1);
}
这个函数返回一个值, 作为table的下标 Entry<K,V>[] table = (Entry<K,V>[]) EMPTY_TABLE;

并发说明:由于在某一时刻2个线程获取的下标值相同,那么就会造成以上情况。

2.如果jdk使用1.7的情况下,那么程序会造成死锁,死锁的原因,请看下面的分析:

假如有两个线程P1、P2,以及链表 a=》b=》null
1、P1先执行,执行完"Entry<K,V> next = e.next;"代码后发生阻塞,或者其他情况不再执行下去,此时e=a,next=b

2、而P2已经执行完整段代码,于是当前的新链表newTable[i]为b=》a=》null

3、P1又继续执行"Entry<K,V> next = e.next;"之后的代码,则执行完"e=next;"后,newTable[i]为a《=》b,则造成回路,while(e!=null)一直死循环







posted @ 2018-02-07 10:37  anxbb  阅读(138)  评论(0编辑  收藏  举报