美文网首页
为什么说ArrayList和LinkedList是线程不安全

为什么说ArrayList和LinkedList是线程不安全

作者: 蜡笔没了小新_e8c0 | 来源:发表于2019-07-29 20:11 被阅读0次

这里主要是根据源码来对对象进行分析。

1.ArrayList

    /**
     * The array buffer into which the elements of the ArrayList are stored.
     * The capacity of the ArrayList is the length of this array buffer. Any
     * empty ArrayList with elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA
     * will be expanded to DEFAULT_CAPACITY when the first element is added.
     */
    transient Object[] elementData; // non-private to simplify nested class access

    /**
     * The size of the ArrayList (the number of elements it contains).
     *
     * @serial
     */
    private int size;

在ArrayList中主要有两个变量,elementData是一个Object数组,size用来保存节点的个数。

    /**
     * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {@link Collection#add})
     */
    public boolean add(E e) {
        ensureCapacityInternal(size + 1);  // Increments modCount!!
        elementData[size++] = e;
        return true;
    }

这是ArrayList中添加对象的方法,ensureCapacityInternal()主要是用来保证数组存储容量大小的。这里主要可能会导致线程不安全的就是elementData[size++] = e这步操作。看到size++就知道这不是一个原子操作,其主要分为赋值和加1两步。我们可以把该过程分为如下两步:

   elementData[size] = e;
   size = size + 1;

例子

假设此时ArrayList中没有元素。

  • A线程执行了ArrayList中的add方法添加了元素X;
  • 在A线程执行到得到size的大小为0时,B线程同样执行了add方法添加了元素Y,并且也得到size的值为0;
  • 然后两个线程都成功执行了add方法;
  • 我们获取ArrayList中的元素和size值会发现size值为2,而元素只有X或Y中的一个。

因为A、B两线程在添加元素时都获取到size的值,并且都为0,所以两个元素会存放到相同的位置,而size却执行了两次加一操作。

2.LinkedList

        final void checkForComodification() {
            if (modCount != expectedModCount)
                throw new ConcurrentModificationException();    
        }

代码中,modCount记录了LinkedList结构被修改的次数。Iterator初始化时,expectedModCount=modCount。任何通过Iterator修改LinkedList结构的行为都会同时更新expectedModCount和modCount,使这两个值相等。通过LinkedList对象修改其结构的方法只更新modCount。所以假设有两个线程A和B。A通过Iterator遍历并修改LinkedList,而B,与此同时,通过对象修改其结构,那么Iterator的相关方法就会抛出异常。这是相对容易发现的由线程竞争造成的错误。

相关文章

网友评论

      本文标题:为什么说ArrayList和LinkedList是线程不安全

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