Diferencia entre ArrayList sincronizado y CopyOnWriteArrayList en la colección Java

Como sabemos que ArrayList no está sincronizado, si varios subprocesos intentan modificar un ArrayList al mismo tiempo, el resultado final no será determinista. Por lo tanto, la sincronización de ArrayList es imprescindible para lograr la seguridad de subprocesos en un entorno de subprocesos múltiples.

Para hacer objetos de Lista, generalmente creamos objetos de la interfaz de Lista y creamos clases de Lista según nuestros requisitos y últimamente agregamos elementos y accedimos, actualizamos sin pensar en la seguridad de subprocesos. Este concepto es fácil y, al mismo tiempo, un poco avanzado porque se ve que la mayoría de los desarrolladores de Java no practican esta técnica al escribir códigos. 

Nota: Synchronized ArrayList es una colección sincronizada, mientras que CopyOnWriteArrayList es una colección concurrente, ya que se realiza manteniendo la concurrencia.

Diferentes formas de lograr la sincronización en ArrayList 

La sincronización en un Arraylist se puede lograr de dos maneras: 

  1. Usando el método sincronizadoList() de la clase de colecciones
  2. Uso de CopyOnWriteArrayList (COWAL)

Ejemplo

Java

// Java Program to Illustrate Synchronized ArrayList
// Using synchronizedList() Method
 
// Importing required classes
import java.util.* ;
 
// Main class
// SynchronizedArrayList
class GFG {
 
    // Main driver method
    public static void main(String[] args) {
 
        // Creating an empty ArrayList of string type
        // By default, non - synchronized List
        List<String> sal = new ArrayList<String>();
 
        // Adding elements to above List
        // using add() method
        sal.add("Geeks");
        sal.add("for");
        sal.add("Geeks");
        sal.add("Computer");
        sal.add("Science");
        sal.add("Portal");
 
        // Printing the above non-synchronised List
        System.out.println(sal);
 
        // Synchronizing above List
        // using SynchronizedList() method
        Collections.synchronizedList(sal);
 
        // Synchronized block to
        // avoid non-deterministic behavior
        synchronized (sal) {
 
            // Using iterators to iterate over elements
            Iterator<String> itrobj = sal.iterator();
 
            // Holds true till there is single element remaining
            while (itrobj.hasNext()) {
                // Printing elements
                // using next() method
                System.out.println(itrobj.next());
            }
        }
    }
}

Producción:

Dado que ambas formas se utilizan para lograr la seguridad de subprocesos en Arraylist. Aparece la pregunta, cuándo usar COWAL y cuándo usar el métodosyncedList () de la clase Collections . Esto se puede entender entendiendo las diferencias entre ellos. La principal diferencia entre ArrayList sincronizado y CopyOnWriteArrayList proviene de su rendimiento, escalabilidad y cómo logran la seguridad de subprocesos. 

¿Por qué apareció CopyOnWriteArrayList cuando Collection.synchronizedList() ya estaba presente?

Entonces, la respuesta es bastante simple porque inicialmente, SynchronizedList se usó en un entorno de subprocesos múltiples, pero tenía algunas limitaciones. Todos sus métodos de lectura y escritura se sincronizaron en el propio objeto de la lista, es decir, si un subproceso está ejecutando el método add(), bloquea otros subprocesos que desean que el iterador acceda a los elementos de la lista. Además, solo un subproceso podía iterar los elementos de la lista a la vez, lo que era ineficiente. Eso fue bastante rígido. Por lo tanto, se requería una recaudación más flexible que permitiera: 

  1. Múltiples subprocesos que ejecutan operaciones de lectura al mismo tiempo.
  2. Un subproceso ejecuta la operación de lectura y otro ejecuta la operación de escritura al mismo tiempo.
  3. Solo un subproceso puede ejecutar operaciones de escritura, mientras que otros subprocesos pueden ejecutar operaciones de lectura simultáneamente.

Para superar estos problemas, finalmente, en Java 5 , se introdujo un nuevo conjunto de clases de colección llamado Concurrent Collections que contenía CopyOnWriteArrayList . La clase CopyOnWriteArrayList está diseñada para habilitar tales funciones de escritura secuencial y lecturas simultáneas. 

Analicemos las características asociadas con ambos que crean una delgada línea de diferencia entre ellos que se enumeran a continuación:  

1. Bloqueo de hilos

Synchronized List bloquea toda la lista para proporcionar sincronización y seguridad de subprocesos durante la operación de lectura o escritura, mientras que CopyOnWriteArrayList no bloquea toda la lista durante estas operaciones. 
La clase CopyOnWriteArrayList funciona según su nombre, es decir , copy-on-write, que realiza diferentes acciones para operaciones de lectura y escritura. Para cada operación de escritura (añadir, establecer, eliminar, etc.), realiza una nueva copia de los elementos de la lista. y para las operaciones de lectura (get, iterator, listIterator, etc.), funciona en una copia diferente. Por lo tanto, no hay sobrecarga adicional durante una operación de lectura y su operación de lectura es más rápida que Collections.SynchronizedList(). Por lo tanto, COWAL es mejor para la operación de lectura que la Lista Sincronizada. 

2. Operaciones de escritura

Para la operación de escritura en ArrayList, las operaciones de escritura de COWAL son más lentas que Collections.synchronizedList(), ya que utiliza Re-entrantLock. El método de escritura siempre creará una copia de la array existente y hará la modificación en la copia y finalmente actualizará la referencia volátil de la array para apuntar a esta nueva array. Por lo tanto, tiene una sobrecarga masiva durante una operación de escritura. Es por eso que las operaciones de escritura de CopyOnWriteArrayList son más lentas que Collections.synchronizedList().

3. Comportamiento durante la modificación

Synchronized List es un iterador a prueba de fallas , es decir, lanzará ConcurrentModifcationException cuando la lista se modifica cuando un subproceso itera sobre ella, mientras que CopyOnWriteArrayList es un iterador a prueba de fallas , es decir, no lanzará ConcurrentModifcationException incluso cuando la lista se modifica cuando un subproceso está iterando sobre él.

4. Número de subprocesos de trabajo

Solo se permite que un subproceso opere en la Lista sincronizada, bloqueando el objeto de la lista completa, lo que afecta su rendimiento ya que otros subprocesos están esperando mientras que, en el caso de COWAL , se permite que varios subprocesos operen en ArrayList, ya que funciona en clones separados. copia para operaciones de actualización/modificación, lo que hace que su rendimiento sea más rápido .

5. Iterando dentro del Bloque

Al iterar la Lista sincronizada, asegúrese de iterar dentro del bloque sincronizado mientras que, en CopyOnWriteArrayList, podemos iterar con seguridad fuera del bloque sincronizado.

¿Cuándo usar SynchronizedList?

  • Dado que en CopyOnWriteArrayList para cada operación de actualización/modificación, se crea una nueva copia clonada por separado y hay una sobrecarga en JVM para asignar memoria y fusionar la copia clonada con la copia original. Por lo tanto, en este caso, SynchronizedList es una mejor opción. Cuando el tamaño de Arraylist es grande.
  • Cuando el tamaño de Arraylist es grande.

¿Cuándo usar CopyOnWriteArrayList?

  • CopyOnWriteArrayList proporciona lectura sin bloqueo, lo que significa un rendimiento mucho mejor si hay más subprocesos de lectura y la escritura es bastante baja.
  • Cuando el tamaño de Arraylist es pequeño.

SynchronizedList v/s CopyOnWriteArrayList

SynchronizedArrayListSynchronizedArrayList  CopyOnWriteArrayList 
Fue introducido en Java versión 1.2 Fue introducido en Java versión 1.5
Debe usarse cuando hay más operaciones de escritura que operaciones de lectura. Debe usarse cuando hay más operaciones de lectura que de escritura.
El iterador utilizado es a prueba de fallas. El iterador utilizado es a prueba de fallas.
La iteración de List tiene que estar dentro del bloque sincronizado.   La iteración de la lista puede estar fuera del bloque sincronizado.
Todo el ArrayList está bloqueado por Synchronized Arraylist para la seguridad de subprocesos durante las operaciones de lectura y escritura.  Todo ArrayList está bloqueado por SynchronizedArrayList para seguridad de subprocesos solo durante las operaciones de escritura.
Se prefiere cuando ArrayList es más grande. Se prefiere cuando ArrayList es más pequeño. 

Publicación traducida automáticamente

Artículo escrito por Tapan rawat y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *