源码分析为什么ArrayList是线程不安全的

一:前言

        相信好多小伙伴在面试的时候被问到:ArrayList是线程安全的吗?或者是ArrayList和LinkedList哪个是线程安全的?当你二选一的时候,脑袋瓜子只会想着选一个,都不知道那就蒙一个吧。。。其实这本就是一个坑,他们的线程都是不安全的,这篇文章就从源码的角度来分析一下为什么ArrayList是线程不安全的。话不多说,上源码!

二:源码分析

        

public class ArrayList<E> extends AbstractList<E>
        implements List<E>, RandomAccess, Cloneable, java.io.Serializable
{
  

    /**
     * 初始容量是10
     */
    private static final int DEFAULT_CAPACITY = 10;

     /**
     * 定义一个数组 用来存储要添加的数据
     */
    transient Object[] elementData; 
     /**
     * 顾名思义:列表大小,elementData中元素的个数
     */
    private int size;
}


===================================================
/**
* 添加方法add
*/
public boolean add(E e) {
        ensureCapacityInternal(size + 1); 
        elementData[size++] = e;
        return true;
    }



private void ensureCapacityInternal(int minCapacity) {
        ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
    }

综合解释一下:

        前面几个字段有相应的注释,简单明了 说一下这个add方法其中的原理:

        ensureCapacityInternal(); 就是将当前要添加的元素追加的列表的后面,判断列表的 elementData 数组的大小是否满足,size+1其实就是给元素个数加1,但是这里会遇到一个问题如果说size+1大于了自身已有的容量,那么就会自动扩容。

        elementData[size++] = e;这样的操作本身就有问题,他不是原子性的操作,我们把它拆分开来是两个表达式:elementData[size]=e; size=size+1;elementData与size都是全局变量,但没有进行sychronization同步处理,如果是遇到多线程的问题,很容易出现值被覆盖的问题。

        问题重现:

                elementData[size]=e;解释:

                开始size=0;当线程A添加元素的时候,他发现size=0,他就把值放到了elementData 下标为0的位置上,此时线程B也在添加元素 他同时发现size=0,他也会把值放到elementData下标为0的位置上

                size=size+1

                线程A继续执行size+1,当前size为1;

                线程B继续执行size+1,当前size为2;

结果:你就会发现elementData下标为0的数据由线程B覆盖了线程A,但是elementData下标为1的数据是null,而此时的size是2,所以说这就出现了线程不安全的问题。

总结来说:就是一个ArrayList在添加元素的时候,会分为两个步骤,

                  1.在相应的位置上添加元素

                  2.增大size的值

都分为两个步骤了,在多线程的时候,如果线程A仅仅执行了一步但是线程A暂停了,此时线程B在添加元素的时候,又开始按照最开始的情况添加元素,此时就会有冲突了,所以说ArrayList是线程不安全的。

  • 5
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值