0 前言
我們知道 ArrayList 非線程安全,需要自己加鎖或者使用
Collections.synchronizedList
包裝.
從JDK1.5開始JUC裡提供了使用 CopyOnWrite 機制實作的并發容器線程安全的 List - CopyOnWriteArrayList,簡稱 COW
1 CopyOnWrite 設計思想
1.1 基本概念
CopyOnWrite 寫時複制.
一般來說就是當我們往一個容器添加元素的時候,不直接往目前容器添加,而是先将目前容器複制出一個新的容器,往新的容器裡添加元素,添加完元素之後,再将原容器引用指向新容器.
即一開始大家都在共享同一内容,當有人想修改該内容時,才會真地把内容copy出去形成一個新的内容然後再改,這是一種延時懶惰政策.
1.2 設計優點
可并發讀 CopyOnWrite 容器,而無需加鎖,因為目前容器不會添加任何元素.
是以這也是一種讀寫分離的思想,讀寫的是不同的容器.
2 繼承體系
- 和 ArrayList 的繼承體系類似
3 屬性
- 保護所有更改器的鎖
- 僅能通過getArray / setArray通路的數組
- lock 記憶體偏移量
4 構造方法
4.1 無參
- 建立一個空 list
4.2 有參
- 建立一個清單,該清單包含指定集合的元素,其順序由集合的疊代器傳回。
- 建立一個儲存給定數組副本的清單
- 下面開始看源碼,到底是如何實作寫時複制的.
5 add(E e)
向 COW 裡添加元素,是需要加鎖的,否則并發寫時 copy 出N個副本!
getArray
- 擷取數組.非priavte,以便也可以從CopyOnWriteArraySet類(直接組合了CopyOnWriteArrayList作為成員變量)通路
setArray
- 将引用設定到新數組
都加鎖,為什麼還需要拷貝數組,而不直接在原數組修改?
- volatile 修飾的是數組引用!簡單的在原來數組修改幾個元素的值,這種操作是無法發揮可見性的,必須通過修改數組記憶體位址
- 在新數組上執行 copyOf,對原數組無任何影響,隻有新數組完全拷貝完成之後,外部才能通路,避免了原數組資料變動可能造成的不良影響