CopyOnWriteArrayList淺析

寫在最前:CopyOnWriteArrayList適合使用在讀操作遠(yuǎn)遠(yuǎn)大于寫操作的場景里,比如緩存

除了加鎖之外,還有一種技術(shù)可以防止并發(fā)修改異常,那就是讀寫分離技術(shù)

常識:

1、JAVA中“=”操作只是將引用和某個對象關(guān)聯(lián),假如同時有一個線程將引用指向另外一個對象,一個線程獲取這個引用指向的對象,那么他們之間不會發(fā)生ConcurrentModificationException,他們是在虛擬機層面阻塞的,而且速度非???,幾乎不需要CPU時間。

2、JAVA中兩個不同的引用指向同一個對象,當(dāng)?shù)谝粋€引用指向另外一個對象時,第二個引用還將保持原來的對象。

分析:

在CopyOnWriteArrayList中,處理寫操作(包括add、remove、set等)是通過Arrays.copyof()來生成新的數(shù)據(jù)對象,之后在新的數(shù)據(jù)對象進(jìn)行讀寫,之后讓舊的引用指向到新的數(shù)據(jù)對象,從而保證每次寫都在新的數(shù)據(jù)對象上,維護(hù)數(shù)據(jù)的一致性(因為要保證寫的一致性,這里要對各種寫操作要加一把鎖,JDK1.6在這里用了重入鎖)

處理讀操作的時候就是在引用的當(dāng)前對象上進(jìn)行讀(包括get,iterator等),不存在加鎖和阻塞,針對iterator使用了一個叫 COWIterator的閹割版迭代器,因為不支持寫操作,當(dāng)獲取CopyOnWriteArrayList的迭代器時,是將迭代器里的數(shù)據(jù)引用指向當(dāng)前 引用指向的數(shù)據(jù)對象,無論未來發(fā)生什么寫操作,都不會再更改迭代器里的數(shù)據(jù)對象引用,所以迭代器也很安全(這里應(yīng)用了常識2)。

CopyOnWriteArrayList中寫操作需要大面積復(fù)制數(shù)組,所以性能肯定很差,但是讀操作因為操作的對象和寫操作不是同一個對象,讀之 間也不需要加鎖,讀和寫之間的同步處理只是在寫完后通過一個簡單的“=”將引用指向新的數(shù)組對象上來,這個幾乎不需要時間,這樣讀操作就很快很安全,適合在多線程里使用,絕對不會發(fā)生并發(fā)修改異常。

引申:

在數(shù)據(jù)量較大時,性能虧損較大,每次進(jìn)行寫操作都會copy一份,而Array則不會,在要求性能的基礎(chǔ)上,可以使用 volatile + arrayList 實現(xiàn)要求,使用了volatile后解決了并發(fā)修改問題,但會引入新的問題,那就是數(shù)組下標(biāo)越界問題,所以此時不應(yīng)使用通常的遍歷方式for,而應(yīng)該使用的是iterator進(jìn)行遍歷。

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

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

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