Cuatro técnicas para utilizar HashMap de forma segura

En este artículo, hablamos de cuatro técnicas para utilizar HashMap de forma segura.

1 método interno: use HashMap separado por hilo

Como se muestra en la figura siguiente, después de que Tomcat recibe la solicitud, llama a los métodos relevantes del controlador, la capa de servicio y la capa de acceso a la base de datos en secuencia.

Cada vez que se accede al método de la capa de servicio serviceMethod, se creará un HashMap separado dentro del cuerpo del método, los parámetros de solicitud relevantes se copiarán en el HashMap y luego se llamará al método DAO para realizar operaciones de base de datos.

Cada subproceso de procesamiento HTTP tiene su propia instancia dentro del cuerpo del método de la capa de servicio HashMap. En un entorno de subprocesos múltiples, no es necesario HashMaprealizar ninguna operación de sincronización.

Esta es también la forma más común y segura que utilizamos, y es la operación más básica de CRUD.

2 Datos de configuración: escritura inicial, solo lectura posterior

Una vez que se inicia el sistema, podemos cargar los datos de configuración en el caché local HashMap. Una vez inicializada la información de configuración, no es necesario escribirla y en el futuro solo se proporcionan operaciones de lectura.

La figura anterior muestra una clase de configuración SimpleConfig muy simple, que tiene un objeto HashMap configMap en su interior. El constructor llama al método de inicialización y la lógica interna del método de inicialización es almacenar los datos de configuración en un HashMap.

La clase SimpleConfig expone el método getConfig al mundo exterior. Después de que el hilo principal inicializa el objeto SimpleConfig, cuando otros hilos llaman al método getConfig, es seguro para subprocesos porque solo hay operaciones de lectura y no de escritura.

3 Bloqueo de lectura-escritura: bloqueo al escribir, lectura paralela, más escenarios de lectura y menos escritura

Un bloqueo de lectura y escritura es un bloqueo dividido en dos partes: un bloqueo de lectura y un bloqueo de escritura. El bloqueo de lectura permite que varios subprocesos lo adquieran al mismo tiempo, mientras que el bloqueo de escritura es un bloqueo de exclusión mutua.

Sus reglas son:<strong style="font-size: heredar;line-height: heredar;color: rgb(255, 104, 39);">La lectura y la lectura no son mutuamente excluyentes, la lectura y la escritura son mutuamente excluyentes y escribir y escribir son mutuamente excluyentes </strong>, adecuados para escenarios comerciales con más lectura y menos escritura.

Generalmente usamos ReentrantReadWriteLock, que implementa ReadWriteLock. La interfaz ReadWriteLock también es muy simple. Proporciona principalmente dos métodos internamente, devolviendo bloqueo de lectura y bloqueo de escritura, respectivamente.

 public interface ReadWriteLock {
    //获取读锁
    Lock readLock();
    //获取写锁
    Lock writeLock();
}

El uso de bloqueos de lectura y escritura es el siguiente:

  1. Cree un objeto ReentrantReadWriteLock. Cuando se usa ReadWriteLock, no se usa directamente, pero obtiene su bloqueo interno de lectura y escritura, y luego llama al método de bloqueo/desbloqueo respectivamente;
private ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
  1. Leer datos compartidos;
Lock readLock = readWriteLock.readLock();
readLock.lock();
try {
   // TODO 查询共享数据
} finally {
   readLock.unlock();
}
  1. Escribir datos compartidos;
Lock writeLock = readWriteLock.writeLock();
writeLock.lock();
try {
   // TODO 修改共享数据
} finally {
   writeLock.unlock();
}

El siguiente código muestra cómo usar ReadWriteLock para usar HashMap de forma segura:

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class ReadWriteLockCache {
  
    // 创建一个 HashMap 来存储缓存的数据
    private Map<String, String> map = new HashMap<>();

    // 创建读写锁对象
    private ReadWriteLock rw = new ReentrantReadWriteLock();

    // 放对象方法:向缓存中添加一个键值对
    public void put(String key, String value) {
        // 获取写锁,以确保当前操作是独占的
        rw.writeLock().lock();
        try {
            // 执行写操作,将键值对放入 map
            map.put(key, value);
        } finally {
            // 释放写锁
            rw.writeLock().unlock();
        }
    }

    // 取对象方法:从缓存中获取一个值
    public String get(String key) {
        // 获取读锁,允许并发读操作
        rw.readLock().lock();
        try {
            // 执行读操作,从 map 中获取值
            return map.get(key);
        } finally {
            // 释放读锁
            rw.readLock().unlock();
        }
    }
}

El uso de bloqueos de lectura y escritura para operar HashMap es una técnica muy clásica. El middleware de mensajes RockeMQ NameServer (servicio de nombres) guarda y consulta información de enrutamiento a través de esta técnica.

Además, los bloqueos de lectura y escritura pueden operar múltiples HashMap. En comparación con ConcurrentHashMap, ReadWriteLock puede controlar la granularidad de los objetos de caché y tiene mayor flexibilidad.

4 Collections.synchronizedMap: Bloqueado para lectura y escritura

El siguiente código, cuando usamos userMap en múltiples subprocesos,

static Map<Long, User> userMap = Collections.synchronizedMap(new HashMap<Long, User>());

Ingrese el método de mapa sincronizado:

public static <K,V> Map<K,V> synchronizedMap(Map<K,V> m) {
       return new SynchronizedMap<>(m);
}

SynchronizedMap contiene un objeto mutex de bloqueo de objeto internamente, que es esencialmente una clase contenedora que vuelve a implementar las operaciones de lectura y escritura de HashMap. Vemos que cada vez que se lee o escribe, se usa la palabra clave sincronizada para garantizar la seguridad del subproceso. operación.

Aunque la técnica Collections.synchronizedMap es muy simple de usar, debemos comprender que se bloqueará cada vez que se lea y escriba, y el rendimiento no será particularmente bueno.

5 Resumen

En este artículo, el autor resume cuatro técnicas seguras para subprocesos para usar HashMap.

1. Dentro del método: cada hilo usa un HashMap separado

Este es el método más utilizado y muy fiable. Cada subproceso crea una instancia dentro del cuerpo del método HashMap. En un entorno de subprocesos múltiples, no HashMapse requieren operaciones de sincronización.

2. Datos de configuración: escritura inicial, solo lectura posterior

Cuando se inicia el middleware, leerá el archivo de configuración y escribirá los datos de configuración en HashMap. Una vez que el hilo principal termine de escribir, no habrá más operaciones de escritura en el futuro y otros hilos podrán leerlo sin causar seguridad para los hilos. asuntos.

3. Bloqueo de lectura-escritura: bloqueo al escribir, lectura paralela, más escenarios de lectura y menos escritura

Un bloqueo de lectura y escritura es un bloqueo dividido en dos partes: un bloqueo de lectura y un bloqueo de escritura. El bloqueo de lectura permite que varios subprocesos lo adquieran al mismo tiempo, mientras que el bloqueo de escritura es un bloqueo de exclusión mutua.

Sus reglas son:<strong style="font-size: heredar;line-height: heredar;color: rgb(255, 104, 39);">La lectura y la lectura no son mutuamente excluyentes, la lectura y la escritura son mutuamente excluyentes y escribir y escribir son mutuamente excluyentes </strong>, adecuados para escenarios comerciales con más lectura y menos escritura.

El uso de bloqueos de lectura y escritura para operar HashMap es una técnica muy clásica. El middleware de mensajes RockeMQ NameServer (servicio de nombres) guarda y consulta información de enrutamiento a través de esta técnica.

4. Collections.synchronizedMap: bloqueado para lectura y escritura

El método Collections.synchronizedMap utiliza el patrón decorador para proporcionar una clase decoradora SynchronizedMap segura para subprocesos para el HashMap no seguro para subprocesos.

SynchronizedMap se utiliza para garantizar indirectamente que la operación de HashMap sea segura para subprocesos, y la capa subyacente de SynchronizedMap también usa la palabra clave sincronizada para garantizar la seguridad de las operaciones para subprocesos.

Los recursos pirateados de "Celebrating More Than Years 2" se cargaron en npm, lo que provocó que npmmirror tuviera que suspender el servicio unpkg. El equipo de inteligencia artificial de Microsoft en China empacó colectivamente y se fue a los Estados Unidos, involucrando a cientos de personas. Biblioteca de visualización frontal y el conocido proyecto de código abierto ECharts de Baidu: "ir al mar" para respaldar a Fish. ¡ Los estafadores utilizaron TeamViewer para transferir 3,98 millones! ¿Qué deberían hacer los proveedores de escritorio remoto? Zhou Hongyi: No queda mucho tiempo para que Google recomiende que todos los productos sean de código abierto. Un ex empleado de una conocida empresa de código abierto dio la noticia: después de ser desafiado por sus subordinados, el líder técnico se enfureció. Despidió a la empleada embarazada. Google mostró cómo ejecutar ChromeOS en una máquina virtual de Android. Por favor, dame un consejo, ¿qué papel juega aquí time.sleep(6)? Microsoft responde a los rumores de que el equipo de IA de China está "haciendo las maletas para Estados Unidos" El People's Daily Online comenta sobre la carga tipo matrioska del software de oficina: Sólo resolviendo activamente los "conjuntos" podremos tener un futuro
{{o.nombre}}
{{m.nombre}}

Supongo que te gusta

Origin my.oschina.net/makemyownlife/blog/11174967
Recomendado
Clasificación