Programación concurrente de Java: bloqueo optimista y bloqueo pesimista

Control de concurrencia

Cuando puede haber concurrencia en el programa, necesitamos usar ciertos medios para asegurar la precisión de los datos en el caso de concurrencia. Este método asegura que el usuario actual y otros usuarios operen juntos, y que los resultados obtenidos estén separados de él. El resultado de la operación es el mismo. Este método se llama control de concurrencia. El propósito del control de concurrencia es asegurar que el trabajo de un usuario no afecte irrazonablemente el trabajo de otro usuario.

Si no se realiza el control de concurrencia, pueden surgir problemas como lecturas sucias, lecturas fantasma y lecturas no repetibles.

El control de concurrencia que a menudo decimos generalmente está relacionado con el sistema de gestión de bases de datos (DBMS). La tarea de control de concurrencia en el DBMS es asegurar que cuando múltiples transacciones accedan a los mismos datos en la base de datos al mismo tiempo, el aislamiento y la unidad de las transacciones y la unidad de la base de datos no se destruyan.

 

Medios para lograr el control de concurrencia

Los principales medios para lograr el control de concurrencia se pueden dividir aproximadamente en control de concurrencia optimista y control de concurrencia pesimista.
Antes de comenzar la introducción, debe quedar claro: si se trata de un bloqueo pesimista o un bloqueo optimista, es un concepto definido por las personas y puede considerarse como una idea. De hecho, no solo el sistema de base de datos relacional tiene los conceptos de bloqueo optimista y bloqueo pesimista, como hibernar, tair, memcache, etc. tienen conceptos similares. Por lo tanto, los bloqueos optimistas, los bloqueos pesimistas y otros bloqueos de bases de datos no deben compararse.

 

Candado pesimista

Cuando queremos modificar un dato en una base de datos, para evitar que otros lo modifiquen al mismo tiempo, la mejor manera es bloquear directamente los datos para evitar la concurrencia. Este método de usar un mecanismo de bloqueo de la base de datos para bloquear antes de modificar los datos se denomina control de concurrencia pesimista (también conocido como "bloqueo pesimista", Control de concurrencia pesimista, abreviatura "PCC").

Enciclopedia Baidu

Las cerraduras pesimistas, como su nombre indica, tienen fuertes características exclusivas y exclusivas. Se refiere a una actitud conservadora hacia los datos que están siendo modificados por el mundo exterior (incluidas otras transacciones actuales del sistema y el procesamiento de transacciones desde sistemas externos). Por lo tanto, en todo el proceso de procesamiento de datos, los datos están en un estado bloqueado. La implementación de bloqueos pesimistas a menudo depende del mecanismo de bloqueo proporcionado por la base de datos (solo el mecanismo de bloqueo proporcionado por la capa de base de datos puede garantizar realmente la exclusividad del acceso a datos, de lo contrario, incluso si el mecanismo de bloqueo se implementa en este sistema, no hay garantía de que el sistema externo no se modifique Datos).

La razón por la que se llama bloqueo pesimista es porque es un método de control de concurrencia que tiene una actitud pesimista hacia la modificación de datos. En general, creemos que la probabilidad de que los datos se modifiquen simultáneamente es relativamente alta, por lo que debemos bloquear antes de modificar.

Las cerraduras pesimistas son cerraduras principalmente compartidas o exclusivas

  • El bloqueo compartido también se denomina bloqueo de lectura o bloqueo S para abreviar. Como su nombre lo indica, los bloqueos compartidos significan que varias transacciones pueden compartir un bloqueo para los mismos datos y pueden acceder a los datos, pero solo pueden leerlos y no pueden modificarlos.
  • Los bloqueos exclusivos también se llaman bloqueos de escritura o bloqueos X para abreviar. Como su nombre lo indica, los bloqueos exclusivos no pueden coexistir con otros bloqueos. Si una transacción adquiere un bloqueo exclusivo para una fila de datos, otras transacciones ya no pueden adquirir otros bloqueos para esa fila, incluidos los bloqueos compartidos y exclusivos, pero las transacciones que adquieren bloqueos exclusivos son posibles. Leer y modificar filas de datos.

El control de concurrencia pesimista es en realidad una estrategia conservadora de "buscar bloqueo antes del acceso", que proporciona una garantía para la seguridad del procesamiento de datos.

Pero en términos de eficiencia, el mecanismo de manejo del bloqueo causará una sobrecarga adicional para la base de datos y aumentará la posibilidad de un punto muerto. Además, reducirá el paralelismo. Si una transacción bloquea una fila de datos, otras transacciones deben esperar a que la transacción se complete antes de procesar esa fila de datos.

 

Bloqueo optimista (bloqueo optimista)

El bloqueo optimista es relativo al bloqueo pesimista.El bloqueo optimista supone que los datos no causarán conflictos en circunstancias normales, por lo que cuando los datos se envían para su actualización, verificará formalmente si los datos entran en conflicto o no. Si se encuentra un conflicto, regrese Proporcione al usuario la información incorrecta y deje que el usuario decida cómo hacerlo.

Enciclopedia Baidu

El mecanismo de bloqueo optimista ha adoptado un mecanismo de bloqueo más relajado. Los bloqueos optimistas son bloqueos relativamente pesimistas, y también son un mecanismo para evitar los errores de procesamiento de datos causados ​​por las lecturas fantasmas de la base de datos y el tiempo de procesamiento comercial excesivo. Sin embargo, los bloqueos optimistas no utilizarán deliberadamente el mecanismo de bloqueo de la base de datos, sino que se basan en los datos en sí Para garantizar la precisión de los datos.

En comparación con el bloqueo pesimista, el bloqueo optimista no utiliza el mecanismo de bloqueo proporcionado por la base de datos cuando procesa la base de datos. La forma general de lograr un bloqueo optimista es registrar la versión de los datos.

El control de simultaneidad optimista cree que la probabilidad de carreras de datos entre transacciones es relativamente pequeña, por lo que debe hacerse directamente tanto como sea posible, y no se bloqueará hasta que se confirme, por lo que no se producirán bloqueos ni puntos muertos.

 

Darse cuenta de manera

Implementación de bloqueo pesimista

La realización del bloqueo pesimista a menudo se basa en el mecanismo de bloqueo proporcionado por la base de datos. En la base de datos, el proceso de bloqueo pesimista es el siguiente:

  1. Antes de modificar el registro, intente agregar un bloqueo exclusivo al registro.
  2. Si el bloqueo falla, se modifica el registro, por lo que la consulta actual puede tener que esperar o lanzar una excepción. El desarrollador determina el método de respuesta específico de acuerdo con las necesidades reales.
  3. Si el bloqueo se agrega con éxito, el registro se puede modificar y la transacción se desbloqueará después de que se complete la transacción.
  4. Mientras tanto, si hay otras operaciones que modifican el registro o agregan un bloqueo exclusivo, esperaremos a que desbloqueemos o arrojemos directamente una excepción.

Tome el motor MySodl Innodb de uso común como ejemplo para ilustrar cómo usar el bloqueo pesimista en SQL.

Para usar el bloqueo pesimista, debemos desactivar la propiedad de confirmación automática de la base de datos MySQL. Debido a que MySQL usa el modo de confirmación automática de forma predeterminada, es decir, cuando realizamos una operación de actualización, MySQL enviará los resultados de inmediato. (Declaración SQL: establecer autocommit = 0)

Para ilustrar el uso de bloqueos pesimistas con la necesidad de deducir el inventario durante la colocación de la orden de Taobao:

Como se indicó anteriormente, antes de modificar el registro con id = 1, primero bloquéelo para actualizarlo y luego modifíquelo. Esta es la estrategia de bloqueo pesimista más típica.

Si el código anterior para modificar el inventario se produce simultáneamente, solo un subproceso puede abrir la transacción y obtener el bloqueo con id = 1 al mismo tiempo. Otras transacciones deben esperar a que la transacción se envíe para su ejecución. De esta manera podemos garantizar que los datos actuales no serán modificados por otras transacciones.

Como mencionamos anteriormente, el uso de select ... para la actualización bloqueará los datos, pero debemos prestar atención a algunos niveles de bloqueo, el bloqueo de nivel de fila predeterminado de MySQL InnoDB. Los bloqueos a nivel de fila se basan en índices. Si una instrucción SQL no puede usar un índice, no se usarán bloqueos a nivel de fila. Los bloqueos a nivel de tabla se usarán para bloquear toda la tabla. Esto requiere atención.

Implementación de bloqueo optimista

El uso del bloqueo optimista no requiere el uso de mecanismos de bloqueo de la base de datos.

El concepto de bloqueo optimista ha elaborado sus detalles de implementación específicos. Hay dos pasos principales: detección de conflictos y actualización de datos. Hay una forma más típica de su implementación es CAS (Comparar e Intercambiar).

CAS es una tecnología de bloqueo optimista. Cuando varios subprocesos intentan usar CAS para actualizar la misma variable al mismo tiempo, solo uno de los subprocesos puede actualizar el valor de la variable, mientras que los otros subprocesos fallan. El subproceso fallido no se suspende, pero está Informe al fracaso de esta competencia e intente nuevamente.

Por ejemplo, el problema de deducción de inventario anterior se puede lograr mediante un bloqueo optimista de la siguiente manera:

Arriba, antes de actualizar, primero verificamos la cantidad de inventario actual (cantidad) en la tabla de inventario, y luego, al actualizar, usamos la cantidad de inventario como condición de modificación. Cuando enviamos una actualización, juzgamos que el número de inventario actual del registro correspondiente en la tabla de la base de datos se compara con el número de inventario que se sacó por primera vez. Si el número de inventario actual de la tabla de la base de datos es igual al número de inventario que se sacó por primera vez, se actualizará. De lo contrario, se consideran datos obsoletos.

La declaración de actualización anterior tiene un problema más importante, a saber, el legendario problema ABA .

Por ejemplo, si un hilo uno toma el inventario número 3 de la base de datos, entonces otro hilo dos también toma el inventario número 3 de la base de datos, y dos realiza algunas operaciones para convertirse en 2, y luego dos convierte el número de inventario en 3 nuevamente. Cuando el subproceso uno realiza la operación CAS, se descubre que la base de datos sigue siendo 3, y luego la única operación es exitosa. Aunque la operación CAS del subproceso uno es exitosa, no significa que este proceso no sea un problema.

Hay una mejor manera de resolver el problema ABA, es decir, a través de un solo campo de versión que puede incrementarse secuencialmente. Cambie al siguiente método:

Cada vez que el bloqueo optimista realiza una operación de modificación de datos, traerá un número de versión. Una vez que el número de versión y el número de versión de datos son consistentes, puede realizar la operación de modificación y realizar una operación +1 en el número de versión, de lo contrario la ejecución falla. Debido a que el número de versión de cada operación aumentará en consecuencia, no habrá ningún problema ABA, porque el número de versión solo aumentará y no disminuirá.

Además de la versión, también puede usar marcas de tiempo, porque las marcas de tiempo aumentan naturalmente en orden.

De hecho, el SQL anterior todavía tiene ciertos problemas: una vez que se encuentra una alta concurrencia, solo se puede modificar con éxito un subproceso, y luego habrá una gran cantidad de fallas.

Para los sitios de comercio electrónico como Taobao, la alta concurrencia es una ocurrencia común, y obviamente no es razonable dejar que los usuarios perciban el fracaso. Por lo tanto, todavía tenemos que encontrar formas de reducir la granularidad del bloqueo optimista.

¡Hay una mejor sugerencia, que puede reducir la fuerza de bloqueo optimista, maximizar la tasa de rendimiento y mejorar la concurrencia! Como sigue:

En la declaración SQL anterior, si el número de pedidos realizados por el usuario es 1, el control de bloqueo optimista se realiza mediante la cantidad-1> 0.

Durante la ejecución de la declaración de actualización anterior, consultará el valor de la cantidad en una operación atómica y lo deducirá por 1.

El control de granularidad de bloqueo es un tema importante en un entorno de alta concurrencia. Elegir un buen bloqueo puede aumentar en gran medida la tasa de rendimiento y el rendimiento al tiempo que garantiza la seguridad de los datos.

 

Como elegir

En la elección del bloqueo optimista y el bloqueo pesimista, observe principalmente la diferencia entre los dos y los escenarios aplicables.

  1. El bloqueo optimista realmente no se bloquea y es altamente eficiente. Una vez que la granularidad del bloqueo no se comprende bien, la probabilidad de falla de actualización será relativamente alta, y es probable que ocurra una falla comercial.

  2. Los bloqueos pesimistas se basan en bloqueos de bases de datos y son ineficientes. La probabilidad de falla de actualización es relativamente baja.

Con la propuesta de las tres arquitecturas altas de Internet (alta concurrencia, alto rendimiento y alta disponibilidad), los bloqueos pesimistas se han utilizado cada vez menos en entornos de producción, especialmente en escenarios comerciales con una cantidad relativamente grande de concurrencia.

1005 artículos originales publicados · 1890 elogiados · 900,000 visitas

Supongo que te gusta

Origin blog.csdn.net/Dream_Weave/article/details/105538696
Recomendado
Clasificación