併發包系列二—— CopyOnWriteArrayList
本系列文章所描述的所有類或介面都是基於 JDK 1.7的原始碼,在其它 JDK 的實現方式中可能會有所不同。
一、簡單介紹
CopyOnWriteArrayList 是一個執行緒安全、並且在讀操作時無鎖的 ArrayList,其具體實現方法如下。
二、CopyOnWriteArrayList()
和 ArrayList 不同,此步的做法為建立一個大小為 0 的陣列。
public CopyOnWriteArrayList() {
setArray(new Object[0]);
}
final void setArray(Object[] a) {
array = a;
}
三、add(E)
add 方法並沒有加上 synchronized 關鍵字,它通過使用 ReentrantLock 來保證執行緒安全。
除了使用 ReentrantLock 來保證執行緒安全外,此處和 ArrayList 的不同是每次都會建立一個新的 Object 陣列,此陣列的大小為當前陣列大小加 1,將之前陣列中的內容複製到新的陣列中,並將新增加的物件放入陣列末尾,最後做引用切換將新建立的陣列物件賦值給全域性的陣列物件。
四、remove(E)
和 add 方法一樣,此方法也通過 ReentrantLock 來保證其執行緒安全,但它和 ArrayList 刪除元素採用的方式並不一樣。
首先建立一個比當前陣列小 1 的陣列,遍歷新陣列,如找到 equals 或均為 null 的元素,則將之後的元素全部賦值給新的陣列物件,並做引用切換,返回 true;如未找到,則將當前的元素賦值給新的陣列物件,最後特殊處理陣列中的最後一個元素,如最後一個元素等於要刪除的元素,則將當前陣列物件賦值為新建立的陣列物件,完成刪除操作,如最後一個元素也不等於要刪除的元素,那麼返回 false。
此方法和 ArrayList 除了鎖不同外,最大的不同在於其複製過程並沒有呼叫 System 的 arrayCopy 來完成,理論上來說會導致效能有一定下降。
五、get(int)
此方法非常簡單,直接獲取當前陣列對應位置的元素,這種方法是沒有加鎖保護的,因此可能會出現讀到髒資料的現象。但相對而言,效能會非常高,對於寫少讀多且髒資料影響不大的場景而言,CopyOnWriteArrayList 是不錯的選擇。
六、iterator()
呼叫 iterator 方法後建立一個新的 COWIterator 物件例項,並儲存了一個當前陣列的快照,在呼叫 next 遍歷時則僅對此快照陣列進行遍歷,因此遍歷 CopyOnWriteArrayList 時不會丟擲 ConcurrentModificatiedException。
從以上的分析可見,CopyOnWriteArrayList 基於 ReentrantLock 保證了增加元素和刪除元素動作的互斥。在讀上沒有做任何鎖操作,這樣就保證了讀的效能,帶來的副作用是有些時候可能會讀取到髒資料。
相關文章
- Java併發包之 CopyOnWriteArrayListJava
- Java併發-CopyOnWriteArrayListJava
- 併發容器之CopyOnWriteArrayList
- java併發之CopyOnWriteArrayListJava
- java併發包學習系列:jdk併發容器JavaJDK
- JDK併發AQS系列(二)JDKAQS
- Java併發指南14:Java併發容器ConcurrentSkipListMap與CopyOnWriteArrayListJava
- java併發資料結構之CopyOnWriteArrayListJava資料結構
- 原始碼|併發一枝花之CopyOnWriteArrayList原始碼
- 併發系列(二)——FutureTask類原始碼簡析原始碼
- 建立併發包
- 「分散式技術專題」併發系列二:基於時間的併發控制分散式
- 併發容器與框架——併發容器(二)框架
- Java併發---concurrent包Java
- MySQL併發複製系列二:多執行緒複製MySql執行緒
- Java併發包原始碼學習系列:同步元件CountDownLatch原始碼解析Java原始碼元件CountDownLatch
- Java併發包原始碼學習系列:同步元件CyclicBarrier原始碼解析Java原始碼元件
- Java併發包原始碼學習系列:同步元件Semaphore原始碼解析Java原始碼元件
- 【Azure DevOps系列】Azure DevOps構建併發布Nuget程式包dev
- Java併發系列—併發程式設計挑戰Java程式設計
- Go 併發程式設計 - 併發安全(二)Go程式設計
- Java 併發包之CountDownLatch、CyclicBarrierJavaCountDownLatch
- 面試系列<3>——java併發面試Java
- JDK併發AQS系列(一)JDKAQS
- JDK併發AQS系列(三)JDKAQS
- JDK併發AQS系列(五)JDKAQS
- Java併發包原始碼學習系列:基於CAS非阻塞併發佇列ConcurrentLinkedQueue原始碼解析Java原始碼佇列
- CopyOnWriteArrayList
- Java併發包原始碼學習系列:ReentrantReadWriteLock讀寫鎖解析Java原始碼
- 突擊併發程式設計JUC系列-併發工具 Semaphore程式設計
- 併發程式設計(二)——併發類容器ConcurrentMap程式設計
- 併發程式設計(二)程式設計
- Java 併發包原子操作類解析Java
- 建立併發布自己的nuget包
- 3.1 JDK併發包之同步控制JDK
- JDK8 併發包一覽JDK
- java併發系列——底層CPUJava
- Java併發系列之volatileJava