[Contenedor concurrente] 3 CopyOnWriteArrayList

3 CopyOnWriteArrayList

Los bloqueos vectoriales y de lista sincronizada tienen gran granularidad, baja eficiencia de simultaneidad y no se pueden editar durante la iteración.

Revise las reglas de diseño del bloqueo de lectura y escritura: se permite que varios subprocesos lean al mismo tiempo y solo un subproceso puede escribir al mismo tiempo (es decir, exclusión mutua escritura-escritura, exclusión mutua lectura-escritura). yLa filosofía de diseño de CopyOnWriteArrayList es que la lectura no está bloqueada en absoluto, y la operación de lectura no se bloqueará al escribir, y solo la escritura y la escritura deben esperar sincrónicamente.

3.1 Un pequeño caso que muestra la función CopyOnWriteArrayList

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. Durante la iteración de ArrayList, si se modifica la estructura de la lista, se activará el mecanismo Fail-Fast y se lanzarán excepciones de modificación simultáneas.
  2. CopyOnWriteArrayList puede modificar la lista al iterar, pero el conjunto de resultados de la iteración aún está antes de la modificación.
  3. Los datos dependen de cuándo se genera el iterador y no se actualizarán después de la iteración.

3.2 Análisis del código fuente

La versión jdk8 de la operación de adición usa ReentrantLock para bloquear y copia internamente los elementos de configuración de la matriz.

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

La versión jdk13 usa bloques de código de sincronización sincronizados y otros cambios no son significativos.

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

No hay ninguna operación de bloqueo para la operación de obtención.

3.3 Desventajas y escenarios aplicables

Desventajas de CopyOnWriteArrayList:

  1. Problema de consistencia de datos: el contenedor CopyOnWriteArrayList solo puede garantizar la consistencia final de los datos, pero no puede garantizar la consistencia de los datos en tiempo real.
  2. Problema de ocupación de memoria: La característica del contenedor CopyOnWrite es el mecanismo de copia de la operación de escritura, habrá dos objetos en la memoria durante la operación de escritura.

Escenarios aplicables: CopyOnWriteArrayList es adecuado para situaciones en las que hay muchas operaciones de lectura y pocas operaciones de escritura.

Supongo que te gusta

Origin blog.csdn.net/LIZHONGPING00/article/details/114274645
Recomendado
Clasificación