multithreading - ¿Son las "carreras de datos" y la "condición de carrera" lo mismo en el contexto de la programación concurrente?
concurrency language-agnostic (4)
No, no son lo mismo. No son un subconjunto el uno del otro. Tampoco son la condición necesaria ni suficiente para el otro.
La definición de raza de datos es bastante clara y, por lo tanto, su descubrimiento puede ser automático. Se produce una carrera de datos cuando dos instrucciones de diferentes subprocesos acceden a la misma ubicación de memoria, al menos uno de estos accesos es una escritura y no hay sincronización que obligue a un orden particular entre estos accesos.
Una condición de carrera es un error semántico. Es un defecto que ocurre en el tiempo o en el orden de los eventos que lleva a un comportamiento erróneo del programa. Muchas condiciones de carrera pueden ser causadas por carreras de datos, pero esto no es necesario.
Considere el siguiente ejemplo simple donde x es una variable compartida:
Thread 1 Thread 2
lock(l) lock(l)
x=1 x=2
unlock(l) unlock(l)
En este ejemplo, las escrituras en x del subproceso 1 y 2 están protegidas por bloqueos, por lo tanto, siempre están sucediendo en algún orden impuesto por el orden con el que se adquieren los bloqueos en tiempo de ejecución. Es decir, la atomicidad de las escrituras no se puede romper; siempre hay un suceso antes de la relación entre los dos escribe en cualquier ejecución. Simplemente no podemos saber qué escritura sucede antes que la otra a priori.
No hay un pedido fijo entre las escrituras, porque las cerraduras no pueden proporcionar esto. Si la corrección de los programas está comprometida, digamos cuando la escritura en x por el hilo 2 es seguida por la escritura en x en el hilo 1, decimos que hay una condición de carrera, aunque técnicamente no existe una carrera de datos.
Es mucho más útil detectar las condiciones de carrera que las carreras de datos; sin embargo, esto también es muy difícil de lograr.
Construir el ejemplo inverso también es trivial. This publicación de blog también explica la diferencia muy bien, con un simple ejemplo de transacción bancaria.
A menudo encuentro que estos términos se usan en el contexto de la programación simultánea. ¿Son lo mismo o diferente?
No, son diferentes y ninguno de ellos es un subconjunto de uno o viceversa.
El término condición de carrera a menudo se confunde con el término raza de datos relacionada, que surge cuando la sincronización no se usa para coordinar todo el acceso a un campo compartido no final. Arriesga una carrera de datos cada vez que un hilo escribe una variable que luego puede leer otro hilo o lee una variable que podría haber sido escrita por otro hilo por última vez si ambos hilos no usan sincronización; el código con razas de datos no tiene una semántica definida útil bajo el Modelo de memoria de Java. No todas las condiciones de carrera son carreras de datos, y no todas las carreras de datos son condiciones de carrera, pero ambas pueden causar que los programas concurrentes fallen de manera impredecible.
Tomado del excelente libro - Java Concurrency in Practice por Joshua Bloch & Co.
Para mí, las carreras de datos son un subconjunto de todas las condiciones de carrera . Las carreras de datos ocurren cuando dos o más hilos acceden a la misma memoria sin un bloqueo adecuado que puede generar valores inesperados (si tiene al menos un hilo haciendo escrituras).
El término condición de carrera en general también podría referirse, por ejemplo, a hilos que se estancan ocasionalmente debido a carreras en la programación de hilos (y un uso inadecuado de los mecanismos de bloqueo).
Según Wikipedia, el término "condición de carrera" ha estado en uso desde los días de las primeras compuertas lógicas electrónicas. En el contexto de Java, una condición de carrera puede pertenecer a cualquier recurso, como un archivo, una conexión de red, un hilo de un grupo de subprocesos, etc.
El término "raza de datos" se reserva mejor para su significado específico definido por el JLS .
El caso más interesante es una condición de carrera que es muy similar a una carrera de datos, pero todavía no es una, como en este ejemplo simple:
class Race {
static volatile int i;
static int uniqueInt() { return i++; }
}
Como i
volátil, no hay una carrera de datos; sin embargo, desde el punto de vista de corrección del programa hay una condición de carrera debido a la no atomicidad de las dos operaciones: leer i
, escribir i+1
. Varios hilos pueden recibir el mismo valor de uniqueInt
.