ArrayList HashMap 都是我们经常使用的数据存储方式,我们也知道对应的存储方式 是线程不安全的,因为什么的原因会导致线程不安全呢?
首先我们先实验对应的ArrayList 的数据结构。
首先先看下在对应的多线程的情况下 会出现的问题。
对应的代码如下:
public static void main(String[] args) throws Exception {
for(int j=0;j<1000;j++) {
ArrayList<Integer> list = new ArrayList();
CountDownLatch countDownLatch = new CountDownLatch(1000);
for (int i = 0; i < 1000; i++) {
new Thread(new MyThread(countDownLatch, list)).start();
}
countDownLatch.await();
System.out.println(list.size());
}
}
static class MyThread implements Runnable{
private ArrayList<Integer> list;
private CountDownLatch countDownLatch;
public MyThread(CountDownLatch countDownLatch, ArrayList<Integer> list ){
this.countDownLatch=countDownLatch;
this.list=list;
}
@Override
public void run(){
countDownLatch.countDown();
for (int i=0;i<10;i++){
list.add(i);
}
}
}
首先为什么size 的值不是10000 的问题:
都说ArrayList是线程非安全的。
我们也看到确实是 在多线程的情况下。确实出现了问题。
主要看到 调用add方法的时候》
有两个步骤:
elementData[size]=e;
size++;
我们这样考虑 :
假如 有 3个线程:
第一个线程 elementData[0]=1; 此时 因为线程的时间到了 执行结束没有继续执行对应的size++;操作
第二个线程 elmentData[0]=2 ;此时以为线程时间到了 执行结束了 没有执行对应的size++操作
此时size应该为2
要说明一点 就是size 假如被压入栈后 是不会再次修改的
但是 因为 没有执行时间到期没有进行++操作,此时 就会被越过 此时对应的size 就是为1 因为两个size全是为0
还会出现为 null 的情况:
这是为什么?