Análisis de habilidades de entrevista: Para ingresar a Ali, releí la implementación de CAS concurrente

Lectura recomendada:

Prefacio

En la entrevista, las preguntas de seguridad de subprocesos concurrentes seguramente serán indispensables, y los principios básicos de CAS también deben entenderse, de modo que se puedan agregar puntos en la entrevista. Echemos un vistazo a las preguntas que la entrevista puede hacer:

  • ¿Qué es el bloqueo optimista y el bloqueo pesimista?

  • ¿Cuál es la realización del bloqueo optimista-CAS (Compare and Swap), CAS (Compare and Swap) principio de realización?

  • Usar en paquete concurrente JDK

  • Los defectos de CAS


1. ¿Qué son el bloqueo optimista y el bloqueo pesimista?

Bloqueo pesimista

Siempre asuma el peor de los casos. Cada vez que se leen datos, se asume que otros hilos cambiarán los datos. Por lo tanto, se requiere una operación de bloqueo. Cuando otros hilos quieren acceder a los datos, deben ser bloqueados y suspendidos. La realización del bloqueo pesimista:

  • Las bases de datos relacionales tradicionales utilizan este mecanismo de bloqueo, como bloqueos de filas, bloqueos de tablas, etc., bloqueos de lectura, bloqueos de escritura, etc., que están todos bloqueados antes de las operaciones;

  • synchronizedImplementación de palabras clave de sincronización en Java .

Cerradura optimista

El bloqueo optimista es en realidad una forma de pensar. Siempre piensa que no habrá problemas de concurrencia. Cada vez que lees datos, piensas que otros subprocesos no modificarán los datos, por lo que no están bloqueados, pero se juzgarán durante la actualización. ¿Otros hilos han modificado los datos? El bloqueo optimista es adecuado para escenarios con muchas operaciones de lectura, lo que puede mejorar el rendimiento del programa. Método para realizar:

  • Implementación CAS: Las variables atómicas bajo el paquete java.util.concurrent.atomic en Java usan una implementación CAS de bloqueo optimista Para el análisis CAS, vea la siguiente sección.

  • Control de número de versión: Generalmente, se agrega un campo de versión de número de versión de datos a la tabla de datos, indicando el número de veces que se han modificado los datos. Cuando se modifican los datos, el valor de la versión aumentará en uno. Cuando el hilo A quiere actualizar el valor de los datos, también leerá el valor de la versión mientras lee los datos. Al enviar la actualización, si el valor de la versión recién leído es igual al valor de la versión en la base de datos actual, se actualizará; de lo contrario, intente nuevamente Actualizar la operación hasta que la actualización sea exitosa

El bloqueo optimista es adecuado para más lecturas y menos escrituras (leer más escenarios), el bloqueo pesimista es más adecuado para más escrituras y menos escenarios de lectura


2. La realización del principio de realización de bloqueo optimista CAS (Compare and Swap), CAS (Compare and Swap)

antecedentes

Antes de jdk1.5, se usaban synchronizedpalabras clave para asegurar la sincronización, synchronizedasegurando que no importa qué hilo mantenga el bloqueo de las variables compartidas, usará acceso exclusivo a estas variables, lo que resulta en estos problemas:

  • En una competencia de subprocesos múltiples, bloquear y liberar bloqueos provocará más cambios de contexto y retrasos en la programación, lo que provocará problemas de rendimiento.

  • Si un hilo sujeta el candado, todos los demás hilos colgarán, esperando que el hilo que sostiene el candado lo libere.

  • Si un subproceso de alta prioridad espera a que un subproceso de baja prioridad libere el bloqueo, provocará una inversión de prioridad, lo que provocará riesgos de rendimiento.

Para optimizar estos problemas de bloqueo pesimista, aparece el bloqueo optimista:

Suponiendo que no hay conflicto de simultaneidad, se opera la misma variable sin bloquear cada vez. Si hay un conflicto de simultaneidad que causa una falla, vuelva a intentarlo hasta que tenga éxito.

Principio CAS (comparar e intercambiar)

El nombre completo de CAS es comparar e intercambiar (comparar e intercambiar), que es un mecanismo utilizado para lograr la sincronización en un entorno multiproceso. También es una optimización sin bloqueo, o giro, y giro adaptativo.

En jdk, CASagregue volatilepalabras clave como la piedra angular de la implementación de paquetes concurrentes. Sin CAS, no habrá ningún paquete concurrente La instrucción CAS se utiliza en java.util.concurrent para implementar un bloqueo optimista que es diferente al sincronizado.

Un mecanismo de implementación típico de bloqueo optimista (CAS):

El bloqueo optimista consta principalmente de dos pasos:

  • Detección de conflictos

  • Actualización de datos

Cuando varios subprocesos intentan usar CAS para actualizar la misma variable al mismo tiempo, solo un subproceso puede actualizar el valor de la variable y otros subprocesos fallarán. El subproceso fallido no se bloqueará, pero se le notificará que la competencia ha fallado. Inténtalo de nuevo.

Para garantizar la seguridad de los subprocesos sin utilizar bloqueos, hay tres operandos importantes en el mecanismo de implementación de CAS:

  • Ubicación de la memoria para leer y escribir (V)

  • Valor original esperado (A)

  • Nuevo valor (B)

Primero lea la ubicación de la memoria (V) que debe leerse y escribirse, y luego compare la ubicación de la memoria (V) que debe leerse y escribirse con el valor original esperado (A). Si la ubicación de la memoria coincide con el valor original esperado A, cambie la ubicación de la memoria a El valor se actualiza al nuevo valor B. Si la ubicación de la memoria no coincide con el valor original esperado, el procesador no hace nada. En cualquier caso, devolverá el valor de esa posición antes de la instrucción CAS. Se puede dividir en tres pasos:

  • Leer (la ubicación de la memoria (V) que debe leerse y escribirse)

  • Comparación (la ubicación de la memoria a leer y escribir (V) y el valor original esperado (A))

  • Escribir de nuevo (nuevo valor (B))


3. Uso de CAS en el paquete concurrente JDK

Java.util.concurrent (JUC java concurrency toolkit) por encima de JDK1.5 se implementa en función del algoritmo CAS. En comparación con el bloqueo exclusivo sincronizado y el algoritmo de bloqueo, CAS es una implementación común del algoritmo sin bloqueo. El uso del bloqueo optimista JUC en el rendimiento Ha habido una gran mejora.

¿Cómo CAS puede garantizar la seguridad de los subprocesos sin usar bloqueos? Observe la clase de operación atómica AtomicInteger :: getAndIncrement () en el paquete concurrente (equivalente a la operación de i ++):

// AtomicInteger中
//value的偏移量
private static final long valueOffset; 
//获取值
private volatile int value;
//设置value的偏移量
static {
       try {
           valueOffset = unsafe.objectFieldOffset
              (AtomicInteger.class.getDeclaredField("value"));
      } catch (Exception ex) { throw new Error(ex); }
  }
//增加1
public final int getAndIncrement() {
       return unsafe.getAndAddInt(this, valueOffset, 1);
  }

Primero, el valor debe ser modificado por volátiles, lo que asegura su visibilidad y orden.

Necesita inicializar la compensación de valor

unsafe.getAndAddInt realiza una operación CAS por desplazamiento, lee datos de la memoria cada vez y realiza una operación +1 en los datos, y luego realiza una operación CAS en los datos originales y el resultado después de +1. Si tiene éxito, se devuelve el resultado; de lo contrario, volverá a intentarlo hasta Hasta aquí.

//unsafe中
pblic final int getAndAddInt(Object var1, long var2, int var4) {
   int var5;
   do {
       //使用偏移量获取内存中value值
       var5 = this.getIntVolatile(var1, var2);
      //比较并value加+1
  } while(!this.compareAndSwapInt(var1, var2, var5, var5 + var4));
   return var5;
}

JAVA implementa el principio de CAS, unsafe :: compareAndSwapInt se implementa llamando a las instrucciones de bajo nivel de la CPU con la ayuda de C. El siguiente es el código fuente del método sun.misc.Unsafe :: compareAndSwapInt ():

public final native boolean compareAndSwapInt(Object o, long offset,
                                              int expected, int x);

4. Defectos CAS

Problema de ABA

En un escenario de subprocesos múltiples, CAS tendrá problemas de ABA. Por ejemplo, hay 2 subprocesos que realizan operaciones de CAS en el mismo valor (valor inicial A) al mismo tiempo. Estos tres subprocesos son los siguientes

Subproceso 1, el valor esperado es A, el valor a actualizar es B

Subproceso 2, el valor esperado es A, el valor a actualizar es B

Subproceso 3, el valor esperado es B, el valor a actualizar es A

  • El subproceso 1 obtiene primero el segmento de tiempo de la CPU y el subproceso 2 se bloquea por otras razones. El valor del subproceso 1 se compara con el valor esperado de A, se encuentra que es igual y el valor se actualiza a B.

  • En este momento, aparece el hilo 3. El valor del hilo 3 se compara con el valor esperado B. Si se encuentra que es igual, el valor se actualiza a A

  • En este momento, el hilo 2 se recupera del bloque y obtiene el segmento de tiempo de la CPU. En este momento, el valor del hilo 2 se compara con el valor esperado A, y si se encuentra que es igual, el valor se actualiza a B. Aunque el hilo 2 también ha completado la operación, el hilo 2 no no sé el valor ha pasado por el proceso de A-> B-> A .

El daño causado por los problemas de ABA:

En el cajero automático, Xiao Ming retiró 50 yuanes. Debido al problema del cajero automático, hay dos subprocesos, y el saldo se cambia de 100 a 50 al mismo tiempo. Subproceso 1 (cajero automático): obtenga el valor actual de 100 y espere actualizarlo a 50.

Hilo 2 (cajero automático): obtenga el valor actual de 100, espere actualizar a 50,

El hilo 1 se ejecuta correctamente y el hilo 2 está bloqueado por algún motivo. En este momento, alguien envía 50 a Xiao Ming

Subproceso 3 (predeterminado): Obtenga el valor actual de 50 y espere que se actualice a 100. En este momento, el subproceso 3 se ejecuta correctamente y el saldo se convierte en 100. El subproceso 2 se recupera del Bloque. También obtiene 100. Después de comparar, ¡continúe actualizando el saldo a 50! ! !

En este punto, puede ver que el saldo real debería ser 100 (100-50 + 50), pero en realidad se convierte en 50 (100-50 + 50-50) Esta es la presentación exitosa causada por el problema ABA.

Solución

  • AtomicStampedReference : Referencia de objeto con marca de tiempo para resolver el problema ABA. La función del método compareAndSet de esta clase es comprobar primero si la referencia actual es igual a la referencia esperada y si la bandera actual es igual a la bandera esperada. Si todos son iguales, la referencia y el valor de la bandera se establecen atómicamente al valor actualizado dado.
public boolean compareAndSet(
              V      expectedReference,//预期引用
              V      newReference,//更新后的引用
             int    expectedStamp, //预期标志
             int    newStamp //更新后的标志

)
  • versión : agregue el número de versión delante de la variable, el número de versión de la variable es +1 cada vez que se actualiza la variable, es decir, A-> B-> A se convierte en 1A-> 2B-> 3A

Tiempo de ciclo prolongado y gastos generales elevados

Spin CAS (sin éxito, continuará ejecutándose en un bucle hasta que tenga éxito) si no tiene éxito durante mucho tiempo, traerá una gran sobrecarga de ejecución a la CPU.

Solución:

  • Limite el número de giros para evitar entrar en un bucle sin fin

  • JVM puede admitir la instrucción de pausa proporcionada por el procesador, por lo que la eficiencia se mejorará hasta cierto punto,

Garantizar solo el funcionamiento atómico de una variable compartida

Al realizar operaciones en una variable compartida, podemos usar CAS cíclico para asegurar operaciones atómicas, pero cuando se opera en múltiples variables compartidas, CAS cíclico no puede garantizar la atomicidad de la operación.

Solución:

  • Si necesita operar en múltiples variables compartidas, puede usar el método de bloqueo (bloqueo pesimista) para garantizar la atomicidad,

  • Se pueden combinar varias variables compartidas en una variable compartida para la operación CAS.

Supongo que te gusta

Origin blog.csdn.net/weixin_45784983/article/details/108388399
Recomendado
Clasificación