并发下的ArrayList错误分析

目录

结果1.并发导致数据丢失

结果2.并发导致插入null

结果3.并发导致数组越界

分析:


直接看示例

public class ArrayListTest {

    private static List<String> threadList = new ArrayList<String>();

 

    public static void main(String[] args) {

       try {

           testWriteArrayListError();

       } catch (Exception e) {

           e.printStackTrace();

       }

    }

原文:https://blog.csdn.net/lan861698789/article/details/81697409

    /**

     * @Title: arraylist

     * @author: crazyJava

     * @Description: 测试并发对arraylist的影响

     * @throws Exception

     * @return void

     */

    private static void testWriteArrayListError() throws Exception {

 

       Runnable writeR = new Runnable() {

           public void run() {

              threadList.add(Thread.currentThread().getName());

           }

       };

 

       for (int i = 0; i < 1000; i++) {

           Thread t = new Thread(writeR, i + "");

           t.start();

       }

 

       // 等待子线程执行完

       Thread.sleep(2000);

 

       System.out.println(threadList.size());

       // 输出list中的值

       for (int i = 0; i < threadList.size(); i++) {

           System.out.println("index:" +i + "->" + threadList.get(i));

       }

    }

}

结果1.并发导致数据丢失

结果2.并发导致插入null

996

index:0->0

index:1->1

......

index:107->485

index:108->354

index:109->null

index:110->479

结果3.并发导致数组越界

分析:

以添加为例,代码(JDK1.7):

原文:https://blog.csdn.net/lan861698789/article/details/81697409

public boolean add(E e) {

    ensureCapacityInternal(size + 1);  // Increments modCount!!//代码1

    elementData[size++] = e;//代码2

    return true;

}

private void ensureExplicitCapacity(int minCapacity) {

    if (elementData == EMPTY_ELEMENTDATA) {//第一次add时候,初始化容量大小为: 默认值10 or minCapacity

        minCapacity = Math.max(DEFAULT_CAPACITY, minCapacity);

   }

    modCount++;

    if (minCapacity - elementData.length > 0) {//判断是否需要扩容//代码3

        int oldCapacity = elementData.length;//现在容量大小

        int newCapacity = oldCapacity + (oldCapacity >> 1);//扩容原来容量的1.5

        if (newCapacity - minCapacity < 0) //如果扩容后还是不能满足,则当前容量设置为 需要插入的大小

            newCapacity = minCapacity;

 

        elementData = Arrays.copyOf(elementData, newCapacity);//数组的扩容

    }

}

黄色部分(代码2)可拆分为两条语句:

elementData[size] = e

size ++

结果1和2原因:

假设初始size为0,elementData为空。

当线程A执行完elementData[size] = e;还未执行size++就停止了,此时,size=0; elementData[0]放的是A的value,

然后线程B正常完成一个add操作;此时size=1,elementData[0]里面放的是B的value,把A的value给覆盖了。

然后B继续执行size++; 此时,size=2了。数据结构如下:

结果3原因:

假设初始化size为9,elementData.length也为10,这里处于要扩容的临界点。

当线程A执行完代码1(ensureCapacityInternal(size + 1)),后暂停了。此时未扩容。

然后线程B也执行代码1(ensureCapacityInternal(size + 1)),也没有扩容,然后继续往后正常执行。此时size变为了10了。

然后线程A继续执行代码2,size先变为11,然后在赋值给elementData[10],此时就会抛出数据越界错误。

原文:https://blog.csdn.net/lan861698789/article/details/81697409

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章