Java container in CopyOnWrite

Java container in CopyOnWrite

CopyOnWrite container vessel that is copy-on-write (referred to as COW ), the popular understanding is that when the container element when not directly modify the original and then modify the current container and the contents of the current first copy, then modify, modify the completion of the new container after a reference point to the new container vessel, the benefits of doing so is to read can be complicated by the container, rather than locked, because the current container will not be modified, so CopyOnWrite container is separated from the idea of one kind of reading and writing.

JUC package provides two implementations (the java.util.concurrent) in CopyOnWriteArrayListand CopyOnWriteArraySet, it can be seen from the named Array is achieved by Set.

Below CopyOnWriteArrayListan example look at the implementation:

public class CopyOnWriteArrayList implements List<E>, RandomAccess {
  // 修改时需要加锁
  final transient ReentrantLock lock = new ReentrantLock();
  // 内部通过数组实现
  private transient volatile Object[] array;
  
  // add方法
  // 1. 修改操作先加锁
  // 2. 从原来的数组Arrays.copyOf一份到新的数组
  // 3. 在新的数组中设置元素
  // 4. 设置array引用为新的数组
  public boolean add(E 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();
        }
    }
  
  // remove方法
  // 1. 修改先加锁
  // 2. 分两次把index前后的元素都拷贝到新的数组里
  // 3. 设置array引用为新的数组
  public E remove(int index) {
        final ReentrantLock lock = this.lock;
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            E oldValue = get(elements, index);
            int numMoved = len - index - 1;
            if (numMoved == 0)
                setArray(Arrays.copyOf(elements, len - 1));
            else {
                Object[] newElements = new Object[len - 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index + 1, newElements, index,
                                 numMoved);
                setArray(newElements);
            }
            return oldValue;
        } finally {
            lock.unlock();
        }
    }
  
  // get方法,无锁
  public E get(int index) {
        return get(getArray(), index);
    }
}

The following are CopyOnWriteArraySet:

public class CopyOnWriteArraySet<E> extends AbstractSet<E> {
  // 内部使用CopyOnWriteArrayList实现
  private final CopyOnWriteArrayList<E> al;
  
  // add方法,实际调用CopyOnWriteArrayList的addIfAbsent方法
  public boolean add(E e) {
        return al.addIfAbsent(e);
    }
}

Guess you like

Origin www.cnblogs.com/jieyuefeng/p/12064689.html