[Concurrent container] 3 CopyOnWriteArrayList

3 CopyOnWriteArrayList

Vector and synchronizedList locks have large granularity, low concurrency efficiency, and cannot be edited during iteration.

Review the design rules of the read-write lock: multiple threads are allowed to read at the same time, and only one thread is allowed to write at the same time (ie, write-write mutual exclusion, read-write mutual exclusion). andThe design philosophy of CopyOnWriteArrayList is that reading is not locked at all, and the reading operation will not be blocked when writing, and only writing and writing need to wait synchronously.

3.1 A small case showing the CopyOnWriteArrayList feature

public class CopyOnWriteArrayListIterator {
    
    
    public static void main(String[] args) {
    
    
        // List<String> list = new ArrayList<>();
        List<String> list = new CopyOnWriteArrayList<>();
        list.add("1");
        list.add("3");
        list.add("5");

        Iterator<String> iterator = list.iterator();
        while (iterator.hasNext()) {
    
    
            System.out.println(list);
            String next = iterator.next();
            System.out.println(next);
            
            if ("3".equals(next)) {
    
    
                list.add("100");
            }
        }
    }
}

[1, 3, 5]
1
[1, 3, 5]
3
[1, 3, 5, 100]
5
  1. During ArrayList iteration, if the structure of the list is modified, the Fail-Fast mechanism will be triggered and concurrent modification exceptions will be thrown.
  2. CopyOnWriteArrayList can modify the list when iterating, but the result set of the iteration is still before the modification.
  3. The data depends on when the iterator is generated and will not be updated after the iteration.

3.2 Source code analysis

The jdk8 version of the add operation uses ReentrantLock to lock, and internally copies the array setting elements.

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();
    }
}

The jdk13 version uses synchronized synchronization code blocks, and other changes are not big.

final transient Object lock = new Object(); // 锁

public boolean add(E e) {
    
    
    synchronized (lock) {
    
    
        Object[] es = getArray();
        int len = es.length;
        es = Arrays.copyOf(es, len + 1);
        es[len] = e;
        setArray(es);
        return true;
    }
}

There is no lock operation for the get operation.

3.3 Disadvantages and applicable scenarios

Disadvantages of CopyOnWriteArrayList:

  1. Data consistency issue: The CopyOnWriteArrayList container can only guarantee the final consistency of the data, but cannot guarantee the real-time consistency of the data.
  2. Memory occupancy problem: The feature of CopyOnWrite container is the copy mechanism of write operation. There will be two objects in memory during write operation.

Applicable scenarios: CopyOnWriteArrayList is suitable for situations where there are many read operations and few write operations.

Guess you like

Origin blog.csdn.net/LIZHONGPING00/article/details/114274645