1、是什麼 / 實現原理
-
是寫時複製,是一種延時懶惰策略
-
修改共享資源時,將共享資源copy一份,加鎖後修改,再將原容器的引用指向新的容器。注意添加元素的時候是需要加鎖的,否則多線程寫的時候會Copy出N個副本出來
-
可以對CopyOnWrite容器進行併發的讀,而不需要加鎖,因爲當前容器不會添加任何元素。所以CopyOnWrite容器也是一種讀寫分離的思想,讀和寫不同的容器
-
從JDK1.5開始Java併發包裏提供了兩個使用CopyOnWrite機制實現的併發容器,它們是CopyOnWriteArrayList和CopyOnWriteArraySet
2、應用場景
CopyOnWrite併發容器用於讀多寫少的併發場景。比如白名單,黑名單,商品類目的訪問和更新場景等
3、注意事項
-
減少擴容開銷。根據實際需要,初始化CopyOnWrite容器的大小,避免寫時擴容的開銷。
-
使用批量添加。因爲每次添加,容器每次都會進行復制,所以減少添加次數,可以減少容器的複製次數
public static void addBlackList(Map<String,Boolean> ids) {
blackListMap.putAll(ids);
}
4、缺點
-
內存佔用問題。新舊對象同時存在,GC頻繁
-
數據一致性問題。CopyOnWrite只保證最終一致,不保證實時一致
5、自己實現CopyOnWriteMap
public class CopyOnWriteMap<K, V> implements Map<K, V>, Cloneable {
private volatile Map<K, V> internalMap;
public CopyOnWriteMap() {
internalMap = new HashMap<>();
}
@Override
public V put(K key, V value) {
synchronized (this) {
Map<K, V> newMap = new HashMap<K, V>(internalMap);
V val = newMap.put(key, value);
internalMap = newMap;
return val;
}
}
@Override
public V remove(Object key) {
return null;
}
@Override
public void putAll(Map<? extends K, ? extends V> newData) {
synchronized (this) {
Map<K, V> newMap = new HashMap<K, V>(internalMap);
newMap.putAll(newData);
internalMap = newMap;
}
}
}