美文网首页
为什么ArrayList是线程不安全的?

为什么ArrayList是线程不安全的?

作者: nitricoxide | 来源:发表于2021-01-26 15:01 被阅读0次

    先看看多个线程同时对一个ArrayList进行add的操作

    public static void main(String[] args) throws InterruptedException {
        ArrayList<Integer> list = new ArrayList<>();
    
        Thread thread0 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                list.add(i);
            }
        });
    
        Thread thread1 = new Thread(() -> {
            for (int i = 0; i < 100; i++) {
                list.add(i);
            }
        });
    
        thread0.start();
        thread1.start();
    
        Thread.sleep(100);
    
        System.out.println(list.size());
    
    }
    

    结果:

    Exception in thread "Thread-0" java.lang.ArrayIndexOutOfBoundsException: 10
        at java.util.ArrayList.add(ArrayList.java:459)
        at com.ldy.demoz.delete.Test.lambda$main$0(Test.java:21)
        at java.lang.Thread.run(Thread.java:745)
    101
    

    看一下报错行源码:


    原因

    1. 列表大小为9,即size=9
    2. 线程0开始进入add方法,这时它获取到size的值为9,调用ensureCapacityInternal方法进行容量判断。
    3. 线程1此时也进入add方法,它获取到size的值也为9,也开始调用ensureCapacityInternal方法。
    4. 线程0发现需求大小为10,而elementData的大小就为10,可以容纳。于是它不再扩容,返回。
    5. 线程1也发现需求大小为10,也可以容纳,返回。
    6. 线程0开始进行设置值操作, elementData[size++] = e 操作。此时size变为10。
    7. 线程1也开始进行设置值操作,它尝试设置elementData[10] = e,而elementData没有进行过扩容,它的下标最大为9。于是此时会报出一个数组越界的异常ArrayIndexOutOfBoundsException.
      (具体源码可参考ArrayList源码分析

    一句话来说就是ArrayList的操作不是原子性的。

    相关文章

      网友评论

          本文标题:为什么ArrayList是线程不安全的?

          本文链接:https://www.haomeiwen.com/subject/skhazktx.html