java並發容器CopyOnWriteArrayList 使用場景和內部實現分析


java並發容器CopyOnWriteArrayList
CopyOnWriteArrayList
顧名思義,當數組有變化時重新建立一個新的數組

其設計是對於線程安全容器Vector使用中出現問題的一種解.
在Vector容器中,當需要執行復合操作
例如:
//代碼1

class Observable 
{
private List<Observer> observers=new Vector<Observer>();

public void addObserver(){...}
public void removeObserver(){...}
public void notify()
{
Iterator<Observer> itr=observers.iterator();
while(itr.hasNext()){
Observer observer=itr.next();
observer.notify();
}
return;
}
}

 

Observable中的notify方法在單線程中的實現是正常的,但在多線程中,由於在notify執行過程中observers數組的內容可能會發生改變,導致遍歷失效.即使observers本身是線程安全的也於是無補

通常解決這個問題,可以使用同步方法或者加鎖
//代碼2

class Observable 
{
private List<Observer> observers=new Vector<Observer>();

public synchronized void addObserver(){...}

public synchronized void removeObserver(){...}

//同步方法
public synchronized void notify()
{
Iterator<Observer> itr=observers.iterator();
while(itr.hasNext()){
Observer observer=itr.next();
observer.notify();
}
return;
}
}

  

這樣的解決方案中notify的同步導致另外一個問題,即活躍性問題.當observers中有很多元素或者每一個元素的notify方法調用需要很久時,此方法將長時間持有鎖.導致其他任何想修改observers的行為阻塞.最后嚴重影響程序性能

CopyOnWriteArrayList即在這種場景下使用.一個需要在多線程中操作,並且頻繁遍歷.
其解決了由於長時間鎖定整個數組導致的性能問題.
其解決方案即寫時拷貝。

我們先來貼出使用CopyOnWriteArrayList的Observable代碼
//代碼3

class Observable 
{
private List<Observer> observers=new CopyOnWriteArrayList<Observer>();

public void addObserver(){...}

public void removeObserver(){...}

public void notify()
{
Iterator<Observer> itr=observers.iterator();
while(itr.hasNext()){
Observer observer=itr.next();
observer.notify();
}
return;
}
}

 

Observable的notify方法和代碼1相同.但其不會有多線程同時操作的問題.其中的奧秘,通過分析源碼可知
當CopyOnWriteArrayList添加或者刪除元素時,其實現為根據當前數組重新建立一個新數組..

Iterator<Observer> itr=observers.iterator();

 


當我們獲取CopyOnWriteArrayList的迭代器時,迭代器內保存當前數組的引用.之后如果別的線程改變CopyOnWriteArrayList中元素,則根據CopyOnWriteArrayList的特性,其實並沒有改變這個迭代器指向數組的內容.

如圖




免責聲明!

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



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