并發(fā)集合4-CopyOnWriteArrayList源碼分析

前言

ArrayList的線程安全的版本,由名稱可以看出這個集合的特點就是:在寫時復制數(shù)組,讀無鎖的的ArrayList。 元素可以為null

定義


實現(xiàn)了List、RandomAccess、Cloneable、java.io.Serializable接口

重要的字段


使用ReentrantLock來保證線程安全,而不是synchronized同步方法;
array緩存數(shù)組只可以通過getArray(),setArray(Object[] a)來訪問,而且是volatile修飾的,保證線程可見性,與ArrayList不同。

構造器

無參構造方法,需要注意的是,ArrayList的無參構造器內(nèi)是將一個空數(shù)組賦給緩沖數(shù)組,使用的是延遲初始化,只有在第一次調(diào)用add方法時才會去創(chuàng)建一個默認長度為10的數(shù)組,并把引用賦給緩沖數(shù)組;而CopyOnWriteArrayList是直接在構造器內(nèi)創(chuàng)建一個長度為0的Object對象數(shù)組,并沒有采取延遲初始化。


集合構造器

外部緩存數(shù)組構造器,將構造器內(nèi)的參數(shù)數(shù)組作為CopyOnWriteArrayList內(nèi)部的緩沖數(shù)組

add方法

add到尾部


可見在每一次add方法都將復制一遍數(shù)組,并創(chuàng)建一個長度+1的新數(shù)組,然后將新添加的元素放入到數(shù)組的最后,然后更新緩存數(shù)組的引用。

add到指定位置(隨機訪問API)


當添加的位置在數(shù)組的尾部在只需復制一次數(shù)組,當位于中間位置則需要復制兩次。

remove方法

刪除第一個與指定元素相等的集合內(nèi)元素,我們發(fā)現(xiàn)對remove方法的優(yōu)化,即利用array數(shù)組的線程可見性,無鎖獲取一個快照,如果在這個快照中沒有指定元素則返回false,如果含有指定元素,需要調(diào)用remove(Object o, Object[] snapshot, int index)方法加鎖進行遍歷并刪除。即避免了在不含有指定元素的情況下加鎖遍歷的過程。


需要注意indexOf方法是通過equal方法比較是否存在的。

私有方法




刪除指定位置上的元素



當刪除的元素在數(shù)組的末尾則只進行一次數(shù)組復制,當個刪除的元素位于中間則需要復制兩次數(shù)組,最后更新數(shù)組應用。

get方法

無鎖獲取元素,性能較高;但是array的元素的變化還沒有刷新到主內(nèi)存上(set方法,通過鎖來保證元素的可見性)、或者復制數(shù)組的過程中,還沒有更新數(shù)組引用(add方法);即鎖還沒有釋放,這時另外一個線程去讀,所以會出現(xiàn)臟讀。



注意:volatile數(shù)組的可見性問題
volatile的數(shù)組只針對數(shù)組的引用具有volatile的語義,而不是它的元素

size和isEmpty方法

同樣會出現(xiàn)臟讀,比如add方法在復制數(shù)組的過程中,此時調(diào)用size、isEmpty方法


iterator迭代器方法

iterator 和 listIterator 的弱一致性


COWIterator不支持的方法

下面分析中iterator和listIterator都記為iterator

  1. 調(diào)用iterator方法后會創(chuàng)建一個新的COWIterator對象實例(實現(xiàn)了ListIterator接口),并保存了一個當前數(shù)組的快照,在調(diào)用next遍歷時則僅僅對此快照數(shù)組進行遍歷,因此 CopyOnWriteArrayList不會拋出ConcurrentModificatiedException異常,但是會出現(xiàn)臟讀問題。
  1. 由于是對快照進行操作所以迭代器方法僅支持讀操作,不支持和寫操作相關的任何操作(如 remove,set,add),調(diào)用將拋出NoSuchElementException異常。

其他方法列表


總結

CopyOnWriteArrayList 基于ReentranLock保證了增加元素和刪除元素動作的互斥。每一次寫操作(remove,add等相關的)都將會創(chuàng)建數(shù)組復制元素,這將造成頻繁寫極大的性能消耗。在讀操作上沒有加鎖,保證了讀的性能,但是卻會出現(xiàn)臟讀的問題(get、iterator、size、isEmpty)。綜上CopyOnWriteArrayList 適合讀多寫少,對實時性不敏感的應用場景。
允許null元素

參考鏈接
http://ifeve.com/java-copy-on-write/
http://caoyaojun1988-163-com.iteye.com/blog/1754686

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容