Comprensión profunda de jvm-sincronizado (implementación segura para subprocesos)

Este artículo es una nota de lectura.

1. Método de implementación: sincronización mutuamente exclusiva (la sincronización mutuamente exclusiva es una estrategia de concurrencia pesimista)

La sincronización significa que cuando varios subprocesos acceden a los datos compartidos simultáneamente, se garantiza que los datos compartidos sean utilizados por un solo subproceso al mismo tiempo.
La exclusión mutua es un medio para lograr la sincronización. La sección crítica (CriticalSection), mutex (Mutex) y semaphore (Semaphore) son métodos comunes de exclusión mutua.
La exclusión mutua es la causa y la sincronización es el resultado; la exclusión mutua es el método y la sincronización es el final.


En Java, el medio más básico de sincronización mutuamente excluyente es la palabra clave sincronizada:

Después de que Javac compila la palabra clave sincronizada, se forman dos instrucciones de código de bytes, monitorenter y monitorexit, antes y después del bloque de sincronización.

Al ejecutar el comando monitorenter, primero intente adquirir el bloqueo del objeto. Si el objeto no está bloqueado, o el subproceso actual ya mantiene el bloqueo para ese objeto, el valor del contador de bloqueo aumenta en uno y el valor del contador de bloqueo disminuye en uno cuando se ejecuta la instrucción monitorexit. Una vez que el valor del contador es cero, se libera el bloqueo. Si la adquisición del bloqueo del objeto falla, el hilo actual debe bloquearse y esperar hasta que el objeto que lo solicita se libere del hilo que lo sujeta.

Mantener un bloqueo es una operación pesada. Si desea bloquear o activar un subproceso , necesita el sistema operativo para ayudarlo a completarlo. Esto inevitablemente entra en la transición del estado de usuario al estado central. La conversión requiere mucho tiempo de procesador.

En segundo lugar, ReentrantLock bajo el paquete JUC también se puede lograr (en comparación con sincronizado con las siguientes características):

· Interrupción de espera: cuando el hilo que sostiene el bloqueo no libera el bloqueo durante mucho tiempo, el hilo de espera puede optar por dejar de esperar y en su lugar manejar otras cosas.

· Bloqueo justo: cuando varios hilos esperan el mismo bloqueo, deben adquirir los bloqueos en secuencia de acuerdo con el orden cronológico de solicitud de bloqueos; los bloqueos injustos no garantizan esto. Cuando se libera el bloqueo, cualquier hilo que espera el bloqueo Existe la posibilidad de obtener un candado. El bloqueo sincronizado no es justo, ReentrantLock también es injusto por defecto, pero puede usar bloqueos justos a través del constructor con valores booleanos. Sin embargo, una vez que se utiliza el bloqueo equitativo, el rendimiento de ReentrantLock disminuirá bruscamente, lo que obviamente afectará el rendimiento.

· Bloquear múltiples condiciones de enlace: se refiere a un objeto ReentrantLock que puede vincular múltiples objetos de condición al mismo tiempo. En sincronizado, el método wait () y el método notify () o notifyAll () del objeto de bloqueo pueden lograr una condición implícita. Si desea asociarse con más de una condición, debe agregar un bloqueo adicional; ReentrantLock no necesita hacer esto, solo llame al método newCondition () varias veces.

Optimización de bloqueo

Spin lock y giro adaptativo

Es decir, girar (ocupado) a la espera de adquirir el bloqueo, lo que evita la pérdida de rendimiento del cambio de contexto después de ingresar al estado de bloqueo cuando se espera que se obtenga el bloqueo, y luego obtener el bloqueo.

Puede usar el parámetro -XX: + UseSpinning para activar, JDK 6 se ha cambiado al predeterminado

Podemos dejar que el subproceso que solicitó el bloqueo "espere un poco", pero no deje pasar el tiempo de ejecución del procesador para ver si el subproceso que mantiene el bloqueo pronto liberará el bloqueo. Para hacer que el hilo espere, solo necesitamos dejar que el hilo realice un bucle ocupado (giro), esta técnica se llama bloqueo de giro.

Si la cerradura está ocupada por un corto tiempo, el efecto de la espera de giro será muy bueno, de lo contrario, si la cerradura está ocupada durante mucho tiempo, el hilo de giro solo consumirá recursos del procesador en vano

Adaptable significa que el tiempo de centrifugado ya no es fijo, sino que está determinado por el tiempo de centrifugado anterior en la misma cerradura y el estado del propietario de la cerradura.

Si en el mismo objeto de bloqueo, la espera de giro acaba de obtener el bloqueo con éxito, y el hilo que sostiene el bloqueo se está ejecutando, entonces la máquina virtual pensará que este giro también tendrá éxito nuevamente, permitiendo que la espera de giro continúe Relativamente más largo, como durar 100 ciclos ocupados. Por otro lado, si un giro rara vez logra adquirir un bloqueo para un cierto bloqueo, puede ser posible omitir directamente el proceso de giro al adquirir este bloqueo en el futuro para evitar el desperdicio de recursos del procesador.

Eliminación de bloqueo

La eliminación de bloqueos significa que el compilador instantáneo de la máquina virtual requiere sincronización para algunos códigos mientras se está ejecutando, pero elimina los bloqueos que se detectan por no tener contención de datos compartidos.

La principal base de decisión para la eliminación del bloqueo es el soporte de datos del análisis de escape

El comportamiento básico del análisis de escape es analizar el alcance dinámico de un objeto: cuando un objeto se define en un método, puede ser referenciado por un método externo, por ejemplo, pasado como parámetro de llamada a otros lugares, llamado método de escape.

Rugosidad

Si la máquina virtual detecta una serie de operaciones fragmentadas que bloquean el mismo objeto, extenderá (agudizará) el rango de sincronización del bloqueo al exterior de toda la secuencia de operación;

Por ejemplo:

lock a(){...}

b(){
a();
a();
a();
}
//那么只会再b()上加一次锁

Cerradura ligera (sin competencia)

Objetivo:
bajo la premisa de que no hay competencia de subprocesos múltiples, reducir el consumo de rendimiento de las cerraduras pesadas tradicionales utilizando el sistema operativo mutex.

Requisitos previos: el
encabezado de objeto de la máquina virtual HotSpot se divide en dos partes: la primera parte se usa para almacenar los datos de tiempo de ejecución del objeto en sí, como HashCode y GCal Age La longitud de esta parte de los datos ocupará 32 o 64 bits en las máquinas virtuales Java de 32 y 64 bits, respectivamente, lo que oficialmente se llama "Mark Word".
Inserte la descripción de la imagen aquí
Esta parte es la clave para realizar un bloqueo ligero y un bloqueo de polarización.

Introducción al trabajo de bloqueo ligero:
cuando el código está a punto de ingresar al bloque de sincronización, si este objeto de sincronización no está bloqueado (el indicador de bloqueo es el estado "01"), la máquina virtual primero establecerá un bloqueo nombrado en el marco de la pila del hilo actual El espacio de registro ** (Registro de bloqueo) se utiliza para almacenar la copia de la MarkWord actual del objeto de bloqueo (el funcionario agrega un prefijo Desplazado a esta copia, que es la Palabra de marca desplazada **)

Después de eso, la máquina virtual utilizará la operación CAS para intentar actualizar la Palabra de marca del objeto a un puntero para Bloquear registro . Si esta acción de actualización es exitosa, significa que el subproceso posee el bloqueo de este objeto , y el bit de la marca de bloqueo (los dos últimos bits de Mark Word) del objeto Mark Word cambiará a "00" , lo que indica que este objeto está en un bloqueo ligero Estado.

Si esta operación de actualización falla , significa que hay al menos un hilo que compite con el hilo actual para adquirir el bloqueo del objeto . La máquina virtual primero verificará si la Palabra de marca del objeto apunta al marco de la pila del subproceso actual . Si es así, significa que el subproceso actual ya posee el bloqueo del objeto, entonces se puede ingresar directamente en el bloque de sincronización para continuar la ejecución, de lo contrario significa que el objeto de bloqueo ha sido bloqueado Otros hilos con preferencia . Si más de dos hilos compiten por el mismo candado, el candado liviano ya no es válido y debe expandirse a un candado pesado. El valor de estado del indicador de candado se convierte en "10", que se almacena en Mark Word. Es el puntero al bloqueo de peso pesado (mutexe), y el hilo que espera el bloqueo también debe entrar en el estado de bloqueo.

El proceso de desbloqueo también se lleva a cabo mediante la operación CAS. Si la Palabra de marca del objeto todavía apunta al registro de bloqueo del hilo, entonces use la operación CAS para reemplazar la Palabra de marca actual del objeto y la Palabra de marca desplazada copiada en el hilo. Si se puede reemplazar con éxito, todo el proceso de sincronización se completa con éxito;

Los bloqueos livianos pueden mejorar el rendimiento de sincronización del programa según la regla general que "para la mayoría de los bloqueos, no hay competencia en todo el ciclo de sincronización".

Por lo tanto, en el caso de la competencia, las cerraduras livianas serán más lentas que las cerraduras pesadas tradicionales.

La siguiente figura es un diagrama de flujo de la colisión causada por la competencia de bloqueo:
Inserte la descripción de la imagen aquí

Bloqueo de sesgo

El propósito es eliminar las primitivas de sincronización de los datos sin competencia y mejorar aún más el rendimiento del programa.
El bloqueo ligero es utilizar la operación CAS para eliminar el mutex utilizado por la sincronización sin competencia. El bloqueo sesgado es eliminar toda la sincronización sin competencia. Incluso la operación CAS no se realiza.

Significa que el bloqueo estará sesgado hacia el primer subproceso para adquirirlo. Si el bloqueo no ha sido adquirido por otros subprocesos durante la ejecución posterior, el subproceso que mantiene el bloqueo sesgado nunca tendrá que volver a sincronizarse. .
No se requiere sincronización: no es necesario actualizar MarkWord del objeto con CAS

Cuando el subproceso adquiere el objeto de bloqueo por primera vez, la máquina virtual establecerá el bit indicador en el encabezado del objeto en "01" y el modo de polarización en "1", lo que indica que ingresa al modo de polarización . Al mismo tiempo, la operación CAS se utiliza para registrar la ID del hilo que obtuvo el bloqueo en la Palabra de marca del objeto. Si la operación CAS es exitosa, cada vez que el hilo que contiene el bloqueo sesgado ingresa al bloque de sincronización relacionado con el bloqueo, la máquina virtual ya no puede realizar ninguna operación de sincronización (como bloquear, desbloquear y actualizar Mark Word, etc.).
Inserte la descripción de la imagen aquí
A veces, usar el parámetro -XX: -UseBiasedLocking para prohibir la optimización de bloqueo sesgado puede mejorar el rendimiento.

Comparación de las ventajas y desventajas de las cerraduras anteriores.

Inserte la descripción de la imagen aquí

2. Método de implementación: sincronización sin bloqueo

La estrategia de concurrencia optimista basada en la detección de conflictos, en términos simples, es operar primero sin importar el riesgo. Si no hay otro hilo que compita por los datos compartidos, la operación es directamente exitosa; si los datos compartidos se disputan y ocurren conflictos, entonces Para llevar a cabo otras medidas de compensación, la medida de compensación más utilizada es volver a intentar continuamente hasta que no haya competencia por los datos compartidos. También conocido como sin bloqueo

Las instrucciones atómicas proporcionadas por el hardware que implementa la sincronización sin bloqueo incluyen:

  • Prueba y configuración (Prueba y configuración);
  • Obtener y aumentar (Fetch-and-Increment);
  • Intercambiar
  • Compare-and-swap (en adelante denominado CAS);
  • Enlace de carga / almacenamiento de condición (Load-Linked / Store-Conditional, en lo sucesivo denominado LL / SC).

3. Método de implementación: sin esquema de sincronización

Código reentrante (Código reentrante): significa que puede interrumpir el código en cualquier momento durante la ejecución del código y girar para ejecutar otro fragmento de código (incluida la llamada recursiva a sí mismo), y después de que regrese el control, el programa original no aparecerá. Los errores no afectarán los resultados.

Almacenamiento local de subprocesos (Almacenamiento local de subprocesos): si los datos requeridos en un fragmento de código deben compartirse con otro código, compruebe si se puede garantizar que el código que comparte los datos se ejecute en el mismo subproceso. Si se puede garantizar, podemos limitar el rango visible de datos compartidos al mismo hilo, de modo que sin sincronización, también puede garantizar que no haya contención de datos entre hilos.

(ThreadLocal implementa seguridad de subprocesos), abreviado como espacio para el tiempo
, proporciona una copia de la variable para cada subproceso, a fin de lograr un acceso simultáneo sin interferencias

4. Bloquee la semántica de la memoria

La liberación de la cerradura adquiere la relación establecida antes de

Inserte la descripción de la imagen aquí
1) De acuerdo con las reglas de la secuencia del programa, 1 sucede antes de 2, 2 pasa antes de 3; 4 pasa antes de 5, 5 pasa antes de 6.

2) De acuerdo con la regla de bloqueo del monitor, 3 sucede antes que 4.

3) De acuerdo con la transitividad de pasa-antes, 2 pasa-antes 5.

Semántica de memoria de liberación y adquisición de bloqueos

❑ El hilo A libera un bloqueo. En esencia, el hilo A envía un mensaje (modificado por el hilo A a una variable compartida) a un hilo que luego adquirirá el bloqueo.

❑ El hilo B adquiere un bloqueo. En esencia, el hilo B recibió un mensaje de un hilo anterior (modificación de variables compartidas antes de liberar el bloqueo).

❑ El hilo A libera el bloqueo, y luego el hilo B adquiere el bloqueo. Este proceso es esencialmente que el hilo A envía un mensaje al hilo B a través de la memoria principal.

Ejemplo de ReentranLock

Publicado 37 artículos originales · ganado elogios 6 · vistas 4636

Supongo que te gusta

Origin blog.csdn.net/littlewhitevg/article/details/105579769
Recomendado
Clasificación