Establecer la recopilación de clases de seguridad en JUC

Prefacio

La colección de conjuntos está intrínsecamente desordenada en Java, y hay una explicación muy detallada en el código fuente subyacente sobre por qué está desordenada.
Inserte la descripción de la imagen aquí
En esencia, sigue siendo una HashMapcolección que contiene la forma en que se guardan los datos en la clave.
Inserte la descripción de la imagen aquí
Para obtener más detalles sobre por qué es el desorden, puede consultar el contenido de otro blog ( código fuente java - análisis del código fuente hashmap (jdk1.8) ), y no lo explicaré aquí.

¿Por qué no es segura la recopilación de conjuntos normal en subprocesos múltiples?

Como se menciona en el título, ¿por qué la colección de conjuntos es insegura bajo la condición de ejecución multiproceso? Veamos el siguiente caso de código:

import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

public class SetTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        // 不安全
        Set<String> sets = new HashSet();
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                sets.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+sets);
            },String.valueOf(i)).start();
        }
    }
}

Inserte la descripción de la imagen aquí
Cuando una operación de subprocesos múltiples con una colección determinada de objetos, todavía parece aumentar las java.util.ConcurrentModificationExceptionanomalías de datos .

Colecciones seguras bajo Colecciones

Al igual que la forma de crear un conjunto seguro para List en la clase de herramienta de colección Colecciones, también proporciona una forma de crear una colección de conjuntos segura.

import java.util.*;
public class SetTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        // 不安全
        //Set<String> sets = new HashSet();
        Set<String> sets = Collections.synchronizedSet(new HashSet<>());
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                sets.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+sets);
            },String.valueOf(i)).start();
        }
    }
}

El código fuente es similar a la colección de listas:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
también se agrega al método de ejecución de la operación de adición para synchronized 同步代码块garantizar la seguridad de operar la colección de conjuntos en múltiples subprocesos.

Colección de conjuntos de seguridad bajo JUC

También jdk 1.5más adelante, juc para la colección de conjuntos también proporciona clases de colección de conjuntos de seguridad. Como sigue:

import java.util.*;
import java.util.concurrent.CopyOnWriteArraySet;
public class SetTest {
    
    
    public static void main(String[] args) throws InterruptedException {
    
    
        // 不安全
        //Set<String> sets = new HashSet();
        //Set<String> sets = Collections.synchronizedSet(new HashSet<>());
        Set<String> sets = new CopyOnWriteArraySet<>();
        for (int i = 1; i <= 40; i++) {
    
    
            new Thread(()->{
    
    
                sets.add(UUID.randomUUID().toString().substring(0,5));
                System.out.println(Thread.currentThread().getName()+"=="+sets);
            },String.valueOf(i)).start();
        }
    }
}

La lógica del código fuente es la siguiente:
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí
Inserte la descripción de la imagen aquí

Y CopyOnWriteArrayListde tal manera que se aproveche java.util.concurrent.locks.ReentrantLockpara lograr bloquear y desbloquear cerraduras y otras operaciones.

1. Después de llamar al método add, obtenga la información del objeto java.util.concurrent.locks.ReentrantLock.
2. ¡Llame a lock.lock () para obtener el bloqueo!
3. Copie el objeto de matriz original y cree una nueva matriz con el tamaño de la matriz original +1.
4. Coloque los nuevos datos en la nueva matriz.
5. Para cualquier operación, finalmente, se libera el bloqueo.

Supongo que te gusta

Origin blog.csdn.net/qq_38322527/article/details/114756909
Recomendado
Clasificación