本文共 2540 字,大约阅读时间需要 8 分钟。
CopyOnWrite(写时复制),是一种优化策略,主要用于解决共享资源的并发访问问题。在程序设计中,尤其是在多线程环境下,直接共享同一份资源可能导致竞态条件和死锁。CopyOnWrite通过复制资源的方式,实现了对共享资源的安全访问。
CopyOnWrite容器的核心思想是:当资源被修改时,首先创建一个新的副本,然后对副本进行操作。这种方式避免了直接操作共享资源的竞态条件问题。
为了更好地理解CopyOnWrite容器的工作原理,我们可以分析Java的CopyOnWriteArrayList
。在添加元素时,容器会复制当前的数组,并在新数组中添加元素。原数组的引用随后被指向新数组。这种方式确保了读操作可以在不加锁的情况下进行,因为读操作始终操作的是旧数组。
public boolean add(T e) { final ReentrantLock lock = this.lock; lock.lock(); try { Object[] elements = getArray(); int len = elements.length; Object[] newElements = Arrays.copyOf(elements, len + 1); newElements[len] = e; setArray(newElements); return true; } finally { lock.unlock(); }}
为了满足更复杂的键值存储需求,我们可以实现一个简单的CopyOnWriteMap
。其核心思想与CopyOnWriteArrayList
类似:在修改时创建新副本,并对副本进行操作。
public class CopyOnWriteMapimplements Map , Cloneable { private volatile Map internalMap; public CopyOnWriteMap() { internalMap = new HashMap (); } public V put(K key, V value) { synchronized (this) { Map newMap = new HashMap (internalMap); V val = newMap.put(key, value); internalMap = newMap; return val; } } public V get(Object key) { return internalMap.get(key); } public void putAll(Map newData) { synchronized (this) { Map newMap = new HashMap (internalMap); newMap.putAll(newData); internalMap = newMap; } } }
CopyOnWrite容器在读多写少的并发场景中表现尤为出色。例如:
package com.ifeve.book;import java.util.Map;import com.ifeve.book.forkjoin.CopyOnWriteMap;public class BlackListServiceImpl { private static CopyOnWriteMapblackListMap = new CopyOnWriteMap (1000); public static boolean isBlackList(String id) { return blackListMap.get(id) != null; } public static void addBlackList(String id) { blackListMap.put(id, Boolean.TRUE); } public static void addBlackList(Map ids) { blackListMap.putAll(ids); }}
CopyOnWrite容器适用于以下场景:
CopyOnWrite容器通过写时复制机制,为并发编程提供了一种高效的解决方案。它在读多写少的场景中表现优异,但在内存占用和一致性方面存在一定的局限性。开发者在使用时,需要根据具体需求权衡其优缺点。
转载地址:http://wufuk.baihongyu.com/