CopyOnWrite thought

Copy On Write (COW for short) thinking

The idea of ​​CopyOnWrite (COW) is an optimization strategy in the field of computer programming. The core idea is that if there are multiple callers requesting the same resources (such as memory or data storage on disk) at the same time, they will jointly obtain the same pointer to the same resource, until a caller view is modified When the content of the resource, the system will actually copy a private copy to the caller, while the original resource seen by other callers remains unchanged. This process is transparent to other callers. The main advantage of this approach is that if the caller does not modify the resource, no private copy will be created, so multiple callers can share the same resource when just reading.

The realization principle of CopyOnWriteArrayList

Before using CopyOnWriteArrayList, let's read its source code to understand how it is implemented. The following code is the implementation of the add method in CopyOnWriteArrayList (adding elements to CopyOnWriteArrayList). It can be found that locks are needed when adding, otherwise N copies will be copied out when multi-threaded writing.

/** * Appends the specified element to the end of this list.
     *
     * @param e element to be appended to this list
     * @return <tt>true</tt> (as specified by {
        @link Collection#add}) */
    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();
    }
    }

There is no need to lock when reading. If multiple threads are adding data to the CopyOnWriteArrayList when reading, the old data will still be read, because the old CopyOnWriteArrayList will not be locked when writing.

Disadvantages of CopyOnWrite

The CopyOnWrite container has many advantages, but there are also two problems, namely, memory usage and data consistency. So you need to pay attention when developing.

Memory usage problem . Because of the copy-on-write mechanism of CopyOnWrite, during the write operation, the memory of two objects will reside in the memory at the same time, the old object and the newly written object (note: only the reference in the container is copied when copying. Only when writing, new objects are created and added to the new container, and the objects of the old container are still in use, so there are two copies of object memory). If the memory occupied by these objects is relatively large, say about 200M, then write 100M data into it, the memory will occupy 300M, then this time is likely to cause frequent Yong GC and Full GC. Previously, we used a service in our system. Because we used the CopyOnWrite mechanism to update large objects every night, resulting in a 15-second Full GC every night, the application response time also became longer.

In view of the memory occupation problem, the memory consumption of large objects can be reduced by compressing the elements in the container. For example, if the elements are all decimal numbers, consider compressing it into 36 or 64. Or instead of using the CopyOnWrite container, use other concurrent containers, such as ConcurrentHashMap.

Data consistency issues . The CopyOnWrite container can only guarantee the final consistency of the data, but cannot guarantee the real-time consistency of the data. So if the data you want to write can be read immediately, please do not use the CopyOnWrite container.

Why CopyOnWriteArrayList is safe to run concurrently and has better performance than Vector

We all know that Vector adds synchronized to add, delete, modify, and check methods to ensure synchronization. However, when each method is executed, the lock must be acquired, and the performance will be greatly reduced. CopyOnWriteArrayList only adds locks on additions, deletions, and modifications, but not read Locking performance is better than Vector in terms of reading, and CopyOnWriteArrayList supports the concurrent situation of more reading and less writing.

Guess you like

Origin blog.csdn.net/qq_34743935/article/details/113604607