Offer to come, dig friends take it! I am participating in the 2022 Spring Recruit Punch card activity. Click here for details.

1. CopyOnWrite container

The basic idea is that multiple threads share the same content, and when one thread wants to modify the content, it will actually copy out the content to form a new content and then modify it. This is a lazy lazy strategy

Concept 2.

The common understanding is that when we add elements to a container, we do not directly add to the current container, but first Copy the current container, Copy the new container, then add elements to the new container, after adding elements, the original container reference to the new container. The advantage of this is that we can do concurrent reads to the CopyOnWrite container without locking, since no elements are being added to the current container. So CopyOnWrite container is also an idea of read-write separation, reading and writing in different containers

2.1 CopyOnWriteArrayList

    /** Reentrant lock -- synchronize all mutation operations */
    final transient ReentrantLock lock = new ReentrantLock();

    /** Data save structure */
    private transient volatile Object[] array;

    /** * Gets the array. Non-private so as to also be accessible * from CopyOnWriteArraySet class. */
    final Object[] getArray() {
        return array;
    }

    /** * Sets the array. */
    final void setArray(Object[] a) {
        array = a;
    }

    /** * The initialization length is 0 */
    public CopyOnWriteArrayList(a) {
        setArray(new Object[0]);
    }

    /** * the argument is a collection ** **@param c the collection of initially held elements
     * @throws NullPointerException if the specified collection is null
     */
    public CopyOnWriteArrayList(Collection<? extends E> c) {
        Object[] elements;
        if(c.getClass() == CopyOnWriteArrayList.class) elements = ((CopyOnWriteArrayList<? >)c).getArray();else {
            elements = c.toArray();
            // c.toArray might (incorrectly) not return Object[] (see 6260652)
            if(elements.getClass() ! = Object[].class) elements = Arrays.copyOf(elements, elements.length, Object[].class); } setArray(elements); }/** * takes an array **@param toCopyIn the array (a copy of this array is used as the
     *        internal array)
     * @throws NullPointerException if the specified array is null
     */
    public CopyOnWriteArrayList(E[] toCopyIn) {
        setArray(Arrays.copyOf(toCopyIn, toCopyIn.length, Object[].class));
    }
Copy the code

Note: When we add elements to a container, we do not directly add elements to the current container. Instead, we Copy the current container to create a new container, and then add elements to the new container. After adding elements, we reference the original container to the new container. Instead of adding data to CopyOnWriteArrayList one by one, the best way to add data to CopyOnWriteArrayList is through the constructor with arguments or by calling addAll to reduce the memory footprint of each underlying copy and frequent GC operations.

2.2 the Add method

public boolean add(E e) {
        final ReentrantLock lock = this.lock;
    	/ / lock
        lock.lock();
        try {
            // Get the original data array
            Object[] elements = getArray();
            // The length of the array
            int len = elements.length;
            // Copy -- length len + 1
            Object[] newElements = Arrays.copyOf(elements, len + 1);
            // Set the newly added data to the end
            newElements[len] = e;
            // Point array to the new newElements -- memory visible (array variable is volatile)
            setArray(newElements);
            return true;
        } finally {
            / / releases the locklock.unlock(); }}public void add(int index, E element) {
        final ReentrantLock lock = this.lock;
        / / lock
        lock.lock();
        try {
            Object[] elements = getArray();
            int len = elements.length;
            if (index > len || index < 0)
                throw new IndexOutOfBoundsException("Index: "+index+
                                                    ", Size: "+len);
            Object[] newElements;
            int numMoved = len - index;
            if (numMoved == 0)
                newElements = Arrays.copyOf(elements, len + 1);
            else {
                newElements = new Object[len + 1];
                System.arraycopy(elements, 0, newElements, 0, index);
                System.arraycopy(elements, index, newElements, index + 1,
                                 numMoved);
            }
            newElements[index] = element;
            setArray(newElements);
        } finally {
            / / releases the locklock.unlock(); }}Copy the code

Note:

  • usingReentrantLockThis ensures that only one writing thread is copying at a time.
  • The array variable array is used withvolatileThe old array application points to the new array; According to thevolatilethehappens-beforeRule: Changes made by a thread to an array reference are visible to the thread.
  • Since the data is being written to a new array, the read and write operations must be performed in two different data containers.

3. Summary

Advantages:

  • Reading and writing are separate
  • Reader threads do not block each other
  • The consistency of the final data is guaranteed at the expense of real-time data. That is, the reader thread is delay-aware of data updates, so there is no wait for the reader thread in this case.

Disadvantages:

  • Memory footprint: Since CopyOnWrite is a copy-on-write mechanism, it can be used during write operations. There will be memory for two objects, the old object and the newly written object. Note: only references in the container are copied, but new objects are created at write time to be added to the new container, while the old container is still in use, so there are two copies of object memory.
  • The CopyOnWrite container guarantees final data consistency but not real-time data consistency

I am ant back elephant, the article is helpful to you like to pay attention to me, the article has incorrect place please give correct comments ~ thank you