**CopyOnWriteArrayList使用了一種叫寫時復制的方法**
當有新元素添加到CopyOnWriteArrayList時,先從原有的數組中拷貝一份出來,然后在新的數組做寫操作,寫完之后,再將原來的數組引用指向到新數組。
由于所有的寫操作都是在新數組進行的,這個時候如果有線程并發的寫,則通過鎖來控制,如果有線程并發的讀,則分幾種情況:
1、如果寫操作未完成,那么直接讀取原數組的數據;
2、如果寫操作完成,但是引用還未指向新數組,那么也是讀取原數組數據;
3、如果寫操作完成,并且引用已經指向了新的數組,那么直接從新數組中讀取數據。
4、CopyOnWriteArrayList的讀操作是可以不用加鎖的。
## CopyOnWriteArrayList的使用場景
CopyOnWriteArrayList 有幾個缺點:
由于寫操作的時候,需要拷貝數組,會消耗內存,如果原數組的內容比較多的情況下,可能導致young gc或者full gc
不能用于實時讀的場景,像拷貝數組、新增元素都需要時間,所以調用一個set操作后,讀取到數據可能還是舊的,雖然CopyOnWriteArrayList 能做到最終一致性,但是還是沒法滿足實時性要求;
CopyOnWriteArrayList **合適讀多寫少的場景**,不過這類慎用
因為誰也沒法保證CopyOnWriteArrayList 到底要放置多少數據,萬一數據稍微有點多,每次add/set都要重新復制數組,這個代價實在太高昂了。在高性能的互聯網應用中,這種操作分分鐘引起故障。
### CopyOnWriteArrayList透露的思想
1、讀寫分離,讀和寫分開
2、最終一致性
3、使用另外開辟空間的思路,來解決并發沖突
~~~
public class CopyOnWriteArrayList<E>
implements List<E>, RandomAccess, Cloneable, java.io.Serializable {
final transient Object lock = new Object();
private transient volatile Object[] elements;
public boolean add(E e) {
synchronized (lock) {
Object[] elements = getArray();
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len + 1);
newElements[len] = e;
setArray(newElements);
return true;
}
}
public E set(int index, E element) {
synchronized (lock) {
Object[] elements = getArray();
E oldValue = get(elements, index);
if (oldValue != element) {
int len = elements.length;
Object[] newElements = Arrays.copyOf(elements, len);
newElements[index] = element;
setArray(newElements);
} else {
// Not quite a no-op; ensures volatile write semantics
setArray(elements);
}
return oldValue;
}
}
private E get(Object[] a, int index) {
return (E) a[index];
}
final Object[] getArray() {
return elements;
}
final void setArray(Object[] a) {
elements = a;
}
~~~
- Java
- Object
- 內部類
- 異常
- 注解
- 反射
- 靜態代理與動態代理
- 泛型
- 繼承
- JVM
- ClassLoader
- String
- 數據結構
- Java集合類
- ArrayList
- LinkedList
- HashSet
- TreeSet
- HashMap
- TreeMap
- HashTable
- 并發集合類
- Collections
- CopyOnWriteArrayList
- ConcurrentHashMap
- Android集合類
- SparseArray
- ArrayMap
- 算法
- 排序
- 常用算法
- LeetCode
- 二叉樹遍歷
- 劍指
- 數據結構、算法和數據操作
- 高質量的代碼
- 解決問題的思路
- 優化時間和空間效率
- 面試中的各項能力
- 算法心得
- 并發
- Thread
- 鎖
- java內存模型
- CAS
- 原子類Atomic
- volatile
- synchronized
- Object.wait-notify
- Lock
- Lock之AQS
- Lock子類
- 鎖小結
- 堵塞隊列
- 生產者消費者模型
- 線程池