Colección de citas famosas - Slogan de motivación - ¿Cómo logra ConcurrentHashMap una seguridad terrestre eficiente?

¿Cómo logra ConcurrentHashMap una seguridad terrestre eficiente?

¿Cómo garantizar que un contenedor sea seguro para subprocesos? ¿Cómo logra ConcurrentHashMap una seguridad terrestre eficiente?

Java proporciona diferentes niveles de soporte de seguridad para subprocesos. En los marcos de recopilación tradicionales, además de los contenedores de sincronización como Hashtable, también proporcionamos los llamados contenedores de sincronización. Podemos llamar al método contenedor proporcionado por la clase de herramienta Colecciones para obtener un contenedor sincronizado (como Collections.synchronizedMap), pero todos utilizan métodos de sincronización muy generales y su rendimiento es relativamente bajo en situaciones de alta concurrencia.

Además, una opción más común es utilizar y subcontratar las clases de contenedor seguras para subprocesos proporcionadas, que proporcionan:

Varios contenedores de concurrencia, como ConcurrentHashMap y CopyOnWriteArrayList.

Varias colas seguras para subprocesos (colas/colas), como ArrayBlockingQueue y SynchronousQueue.

Versiones seguras para subprocesos de varios contenedores pedidos, etc.

1. ¿Por qué necesitas ConcurrentHashMap?

Hashtable en sí es ineficiente porque su implementación básicamente agrega "sincronizado" a varios métodos como put, get y size. En pocas palabras, esto hace que todas las operaciones simultáneas compitan por el mismo bloqueo y un hilo hace lo mismo.

Durante la operación de paso, otros subprocesos solo pueden esperar, lo que reduce en gran medida la eficiencia de las operaciones concurrentes.

Comprensión personal

Es un mecanismo de bloqueo más detallado para lograr un mayor grado de disfrute.

2. Análisis de tablas hash concurrentes

El diseño y la implementación de ConcurrentHashMap se han ido desarrollando.

1.7

Bloquear

Al bloquear segmentos segmento por segmento, hay varios segmentos en un mapa hash y hay varios depósitos en cada segmento. Almacene un enlace. lista en forma de K-V. Al poner datos, obtenga el segmento donde se agrega el elemento a través del hash de clave.

Luego

bloquea el segmento, luego calcula el hash del depósito para el elemento agregado y luego recorre la lista vinculada en el depósito para reemplazar o agregar nodos al depósito.

Tamaño

Calcula dos veces por segmento, regresa si los dos resultados son iguales; de lo contrario, bloquea todos los segmentos y vuelve a calcular.

1.8

Bloqueo CAS

En 1.8, el bloqueo de segmentos no depende y el número de segmentos es consistente con el número de depósitos;

Primero determine si el contenedor está vacío; de ser así, se inicializa. sizeCtl volátil se utiliza como medio de exclusión mutua. Si se encuentra una inicialización competitiva, se detendrá allí y esperará a que se reanude la condición; de lo contrario, CAS establecerá el indicador exclusivo.

(u . compareandswapint(this, SIZECTL, sc, -1)); de lo contrario, inténtelo de nuevo.

Calcule el hash de la clave para obtener la ubicación del depósito que almacena la clave y determine si el depósito está vacío. Si está vacío, utilice CAS para configurar un nuevo nodo.

De lo contrario, utilice la sincronización para bloquear, iterar sobre los datos del depósito y reemplazar o agregar puntos al depósito.

Finalmente, determine si es necesario convertirlo en un árbol rojo-negro y si es necesario expandirlo antes de la conversión.

Tamaño

Uso del cálculo acumulativo de LongAdd

Puntos clave del uso de ConcurrentHashMap

Puntos clave del uso de ConcurrentHashMap

ConcurrentHashMap le permite actualizar y recorrer al mismo tiempo, es decir, cuando se atraviesa el objeto iterador, ConcurrentHashMap también puede realizar operaciones de eliminación y colocación, y los datos atravesados ​​cambiarán con la salida de las operaciones de eliminación y colocación.