CopyOnWriteArrayList read-write separation, weak consistency

table of Contents

 

Why is there CopyOnWriteArrayList?

What is weak consistency

fail-safe特性

to sum up


Why is there CopyOnWriteArrayList?


 

We know that the List implemented by ArrayList and LinkedList are not thread-safe, so there is Vector, which is a thread-safe collection based on ArrayList. However, whether Vector is an add method or a get method, synchronized modification is added . When multi-threaded read and write List must be queued for execution. Obviously, the efficiency is relatively low. Is there a way to improve efficiency so that the thread is asynchronous when reading the List, and synchronous when writing the List? The answer is CopyOnWriteArrayList , which is separated from reading and writing . The advantage is to improve the efficiency of thread access. Let's compare the execution efficiency of CopyOnWriteArrayList and Vector.

import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;

/**
 * @author :jiaolian
 * @date :Created in 2021-01-18 15:28
 * @description:安全list性能对比
 * @modified By:
 * 公众号:叫练
 */
public class SafeListTest {

    private static Vector<String> safeList = new Vector<>();
    //private static CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();

    private static CountDownLatch countDownLatch = new CountDownLatch(2);

    public static void main(String[] args) throws InterruptedException {
        //初始化
        safeList.add("叫练");
        MySerive fishSerive = new MySerive();
        long start = System.currentTimeMillis();
        new Thread(()->{
            fishSerive.read();
            countDownLatch.countDown();
        },"叫练读线程").start();
        new Thread(()->{
            fishSerive.write();
            countDownLatch.countDown();
        },"叫练写线程").start();
        countDownLatch.await();
        System.out.println("花费:"+(System.currentTimeMillis()-start));
    }

    private static class MySerive {
        //读
        public void read() {
            for (int i=0 ;i<1000000; i++) {
                safeList.get(0);
            }
        }

        //写
        public void write() {
            for (int i=0 ;i<100000; i++) {
                safeList.add("叫练");
            }
        }
    }
}

The above code: When the safe set uses Vector, the execution time is 100 milliseconds, when the safe set uses CopyOnWriteArrayList, the execution time is 5000 milliseconds, the magic code? Didn't you say that CopyOnWriteArrayList is more efficient? But the execution time of CopyOnWriteArrayList is 50 times longer than Vector ! By looking at the source code, we found that when CopyOnWriteArrayList writes elements, it is achieved by backing up the array. When the multi-thread synchronization is intense and the amount of data is large, the array will be copied continuously, causing serious memory waste. This is why the time is too long! But we still recognize the idea of ​​separation of reading and writing!

image.png

 

What is weak consistency


import java.util.Iterator;
import java.util.Vector;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * @author :jiaolian
 * @date :Created in 2021-01-18 16:40
 * @description:CopyOnWriteArrayList弱一致性
 * @modified By:
 * 公众号:叫练
 */
public class WeekCopyOnWriteArrayListTest {

    private static CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>();
    //private static Vector<String> safeList = new Vector<>();

    public static void main(String[] args) throws InterruptedException {
        safeList.add("叫");
        safeList.add("练");
        Iterator<String> iterator = safeList.iterator();
        Thread thread = new Thread(()->{
            //删除下标为0的元素
            safeList.remove(0);
        });
        thread.start();
        //主线程等待thread执行完成;
        thread.join();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

}

The above code: the main thread waits for the thread sub-thread to finish executing, and prints the safeList element in a loop, and the final execution result is shown in the figure below

image.png

You may have questions, isn't thread already deleted "call"? Shouldn't the console only print the word "practice"? Why is the word "calling practice" still typed? The reason is that the main thread executes Iterator<String> iterator = safeList.iterator(); and saves the element snapshot, so you can see the execution result. When the thread thread finishes executing At this time, the JVM memory status is shown in the figure below!

image.png

 

fail-safe特性


He mentioned fail-safe, will first mention fail-fast, fail fast literal translation, it is a collection of rapid detection of failure machine system to prevent incorrect operation of the collection! Under normal circumstances, if a thread loops through the collection in iterator mode, another thread also modifies the collection, we test, such as the above code for weak consistency testing, private static CopyOnWriteArrayList<String> safeList = new CopyOnWriteArrayList<>() ; Replace with private static Vector<String> safeList = new Vector<>(); What will happen?

image.png

As shown in the figure above, java.util. ConcurrentModificationException , the collection concurrent modification error, but the CopyOnWriteArrayList executes normally, the reason is that there will be a snapshot of the collection when CopyOnWriteArrayList deletes data.

So he is fail-safe, and Vector is fail-fast!

to sum up


To summarize, we briefly explained the concepts of CopyOnWriteArrayList's read-write separation, weak consistency, fail-safe, and fail-safe with the code, and briefly described the implementation principle. If you like, please like and pay attention. My name is Lian [ Official Account ] , I call and practice.

image.png

 

 

Guess you like

Origin blog.csdn.net/duyabc/article/details/112789993