Existe una "condición de carrera" cuando el código multiproceso (o de otro modo paralelo) que accedería a un recurso compartido podría hacerlo de tal manera que cause resultados inesperados.
Toma este ejemplo:
for ( int i = 0; i < 10000000; i++ )
{
x = x + 1;
}
Si tuvieras 5 hilos ejecutando este código a la vez, el valor de x NO SERÍA 50,000,000. De hecho, variaría con cada ejecución.
Esto se debe a que, para que cada subproceso incremente el valor de x, tienen que hacer lo siguiente: (simplificado, obviamente)
Recuperar el valor de x
Agregue 1 a este valor
Almacene este valor en x
Cualquier hilo puede estar en cualquier paso de este proceso en cualquier momento, y pueden pisarse mutuamente cuando se trata de un recurso compartido. El estado de x puede ser cambiado por otro hilo durante el tiempo entre x se lee y cuando se vuelve a escribir.
Digamos que un hilo recupera el valor de x, pero aún no lo ha almacenado. Otro hilo también puede recuperar el mismo valor de x (porque ningún hilo lo ha cambiado todavía) y luego ambos estarían almacenando el mismo valor (x + 1) en x!
Ejemplo:
Hilo 1: lee x, el valor es 7
Hilo 1: agregue 1 a x, el valor ahora es 8
Hilo 2: lee x, el valor es 7
Hilo 1: almacena 8 en x
Hilo 2: agrega 1 a x, el valor ahora es 8
Hilo 2: almacena 8 en x
Las condiciones de carrera se pueden evitar empleando algún tipo de mecanismo de bloqueo antes del código que accede al recurso compartido:
for ( int i = 0; i < 10000000; i++ )
{
//lock x
x = x + 1;
//unlock x
}
Aquí, la respuesta sale como 50,000,000 cada vez.
Para obtener más información sobre el bloqueo, busque: mutex, semáforo, sección crítica, recurso compartido.