Entiendo los conceptos básicos de qué son las carreras de datos y cómo los bloqueos / mutexes / semáforos ayudan a prevenirlos. Pero, ¿qué sucede si tienes una "condición de carrera" en la cerradura misma? Por ejemplo, dos subprocesos diferentes, tal vez en la misma aplicación, pero que se ejecutan en procesadores diferentes, intentan adquirir un bloqueo al mismo tiempo .
¿Qué pasa entonces? ¿Qué se hace para evitar eso? ¿Es imposible o simplemente improbable? ¿O es una condición de carrera real esperando que suceda?
multithreading
concurrency
locks
Gavin Howard
fuente
fuente
Respuestas:
Imposible. Se puede implementar de diferentes maneras, por ejemplo, a través de Comparar e intercambiar, donde el hardware garantiza la ejecución secuencial. Puede complicarse un poco en presencia de múltiples núcleos o incluso múltiples sockets y necesita un protocolo complicado entre los núcleos, pero todo esto se soluciona.
fuente
Estudie el concepto de operaciones atómicas de "prueba y configuración".
Esencialmente, la operación no se puede dividir: no es posible que dos cosas lo hagan exactamente al mismo tiempo. Verificará un valor, lo establecerá si está claro y devolverá el valor como estaba cuando se realizó la prueba. En una operación de bloqueo, el resultado siempre será "lock == TRUE" después de un test-and-set, la única diferencia es si se estableció o no al inicio.
A nivel de microcódigo en un procesador de núcleo único, esta es una instrucción indivisible y fácil de implementar. Con procesadores múltiples y multinúcleo, se vuelve más difícil, pero como programadores no tenemos que preocuparnos por eso, ya que está diseñado para funcionar por los tipos realmente inteligentes que hacen el silicio. Esencialmente hacen lo mismo: hacer una instrucción atómica que una versión elegante de probar y configurar
fuente
Simplemente ponga el código para entrar en la sección crítica está especialmente diseñado para que una condición de carrera no viole la exclusión mutua.
La mayoría de las veces se utilizan bucles de comparación y configuración atómica que se ejecutan a nivel de hardware
En ausencia de eso, existen soluciones de software bien estudiadas para permitir la exclusión mutua.
fuente
No es posible que dos (o más) subprocesos adquieran bloqueo al mismo tiempo. Hay pocos tipos de métodos de sincronización, por ejemplo:
Espera activa - bloqueo de giro
Pseudocódigo:
XCHG es un ejemplo de operación atómica (existe en la arquitectura x86) que primero establece un nuevo valor para una variable de "bloqueo" y luego devuelve un valor antiguo. Atómico significa que no se puede interrumpir, en el ejemplo anterior entre establecer un nuevo valor y devolver el antiguo. Atómico - resultado determinista pase lo que pase.
Cuando el bloqueo es igual a 0, otro hilo puede ingresar a la sección crítica, mientras el bucle termina.
Hilo suspendido - por ejemplo contando semáforo
Existen dos operación atómica
.Wait()
y.Signal()
y tenemos la variable entera le llamanint currentValue
.Ahora resolver el problema de la sección crítica es realmente fácil:
Pseudocódigo:
Por lo general, su API de subproceso de programación debería permitirle especificar subprocesos simultáneos máximos en la sección crítica del semáforo. Obviamente, hay más tipos de sincronización en sistemas multiproceso (mutex, monitores, semáforos binarios, etc.) pero se basan en las ideas anteriores. Se podría argumentar que los métodos que utilizan la suspensión de subprocesos deberían preferirse a la espera activa (por lo que no se desperdicia la CPU), no siempre es la verdad. Cuando se suspende el subproceso, se realiza una operación costosa llamada cambio de contexto. Sin embargo, es razonable cuando el tiempo de espera es corto (número de hilos ~ número de núcleos).
fuente