ArrayList 線程安全


  都說ArrayList是線程不安全的,那為什么不安全呢。根據官方提供的源碼,

我是這樣理解的,ArrayList的成員方法都不是原子操作的,比如add(E)方法,該方法是在集合的尾部加入一個一個元素.

add(E)源碼如下:

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

   網上的思路大致是這樣的:

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

因為是兩步,所以必然存在A走完了第一步驟,比如將"張三"放在了index=10的地方,此時還沒來得及修改容量,

此時A被掛起,線程B切進來了,因為總容量沒變,所以繼續在尾部添加,於是index=10的位置被B線程的值占用了,

也就是A添加的值操作就被B沖了,后面的操作繼續,A修改容量加1,B修改容量加1。此時容量增加了2,元素只加入了1,所以線程不安全

 

  這樣理解沒問題,只是根據源碼,先執行的是修改容量,然后才是添加元素。這該怎么解釋啊?

先修改了容量,哪怕A被暫停了,B執行了,那么結果也是容量增加了2,哪怕后續的操作發生異常,那也沒問題啊,因為ArrayList是容許空值得啊!!

求解啊,各位大神

 

 

 

繼續研究,更讓人痛苦,下面是測試代碼:

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,但是運行結果不是的,

     所以說,的確是線程不安全的,但是我理解不透啊!!!

 

求指點,路過的各路大神

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM