ArrayList 线程安全

  都说ArrayList是线程不安全的,那为何不安全呢。根据官方提供的源码,java

我是这样理解的,ArrayList的成员方法都不是原子操做的,好比add(E)方法,该方法是在集合的尾部加入一个一个元素.安全

add(E)源码以下:app

  /**
     * 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;
    }

   网上的思路大体是这样的:ide

add(E)操做有两步,1>尾部添加元素 2>修改集合的容量 ,容量加一。测试

由于是两步,因此必然存在A走完了第一步骤,好比将"张三"放在了index=10的地方,此时还没来得及修改容量,this

此时A被挂起,线程B切进来了,由于总容量没变,因此继续在尾部添加,因而index=10的位置被B线程的值占用了,spa

也就是A添加的值操做就被B冲了,后面的操做继续,A修改容量加1,B修改容量加1。此时容量增长了2,元素只加入了1,因此线程不安全线程

 

  这样理解没问题,只是根据源码,先执行的是修改容量,而后才是添加元素。这该怎么解释啊?blog

先修改了容量,哪怕A被暂停了,B执行了,那么结果也是容量增长了2,哪怕后续的操做发生异常,那也没问题啊,由于ArrayList是允许空值得啊!!ci

求解啊,各位大神

 

 

 

继续研究,更让人痛苦,下面是测试代码:

package sourceCode.ArrayList;

import java.util.ArrayList;

public class arrayListTest implements Runnable {

	private ArrayList<Integer> arry = null;

	public arrayListTest(ArrayList<Integer> arry) {
		this.arry = arry;
	}

	@Override
	public void run() {
		for (int i = 0; i < 10; i++) {
			arry.add(1);
		}
		System.out.println(arry.size());

	}

	public static void main(String[] args) {
		ArrayList<Integer> a = new ArrayList<Integer>();
		for (int i = 0; i < 100; i++) {
			new Thread(new arrayListTest(a)).start();
		}
	}
}

 解读:这例子也不是我写的。很好理解,100个线程,每一个线程向集合中添加10个元素,按理最终集合容量应该是1000,可是运行结果不是的,

     因此说,的确是线程不安全的,可是我理解不透啊!!!

 

求指点,路过的各路大神

相关文章
相关标签/搜索