¿Te resulta más fácil leer con fondo crema, un tono de color, más contraste o un texto más grande? Elige tus colores y tu texto una sola vez, para todas las páginas.

Lección gratuita

Condiciones de carrera e interbloqueo

Después de esta lección: Puedo explicar una condición de carrera y un interbloqueo y cómo se evitan.

Lección de 60 min2 comandosLaboratorio de comandos de Linux de cada día: los treinta comandos que se escriben de memoria

Qué es una condición de carrera

Una condición de carrera ocurre cuando dos procesos o hilos cambian el mismo dato a la vez y el resultado depende de quién llega antes. Es uno de los fallos más difíciles de encontrar, porque el programa casi siempre funciona.

Piensa en dos cajas de un supermercado que suman una venta al mismo contador de ventas del día. Si las dos leen el contador a la vez, una venta se pierde.

Al final de esta lección

Nota

Puedo explicar una condición de carrera y un interbloqueo y cómo se evitan.

Palabras clave

PalabraQué significa
Hilouna línea de ejecución dentro de un proceso
Condición de carrerael resultado depende del orden en que se mezclan los pasos
Sección críticael trozo de código que toca datos compartidos
Cerrojouna marca que solo puede tener un hilo a la vez
Interbloqueoprocesos que se esperan unos a otros para siempre
Grafo de esperaun dibujo con una flecha de cada proceso al que espera

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Sumar uno a un contador son tres pasos

La orden contador = contador + 1 parece un solo paso. El procesador la hace en tres: leer el valor, sumar uno y guardar el resultado.

El sistema puede cambiar de proceso entre dos pasos cualesquiera. Si dos hilos hacen la suma a la vez, sus pasos se mezclan, y a veces se pierde una de las sumas.

Ejemplo: dos hilos y un contador

PasoHiloQué haceValor del contadorCopia del hilo
1Alee0A tiene 0
2Blee0B tiene 0
3Asuma0A tiene 1
4Bsuma0B tiene 1
5Aguarda1A tiene 1
6Bguarda1B tiene 1

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Una suma se perdió y nadie lo notó

Dos hilos sumaron uno cada uno y el contador debería valer 2. Vale 1, porque B leyó el 0 antes de que A guardara su resultado.

Si A termina sus tres pasos antes de que B empiece, sale 2. El fallo aparece solo con ciertos órdenes, y por eso cuesta tanto reproducirlo.

Un cerrojo deja pasar un hilo

El trozo de código que toca el dato compartido es la sección crítica. Para protegerla se usa un cerrojo.

Un hilo toma el cerrojo antes de entrar y lo suelta al salir. Si otro hilo lo intenta mientras está tomado, espera. Así los tres pasos de la suma nunca se mezclan con los de otro.

Toma un cerrojo libre y haz algo dentro

Comando
flock ~/cerrojo echo dentro

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

Intenta tomarlo mientras ya está tomado

Comando
flock -n ~/cerrojo -c 'flock -n ~/cerrojo echo otro || echo ocupado'

Se muestra aquí y no se ejecuta. Crea una cuenta gratuita para pulsar Ejecutar y escribirlo en el terminal de tu propio laboratorio.

flock es un cerrojo sobre un archivo

La primera orden toma el cerrojo, escribe dentro y lo suelta al terminar. Funciona a la primera porque nadie más lo tenía.

La segunda toma el cerrojo y, dentro, intenta tomarlo de nuevo con -n, que significa no esperar. No lo consigue y flock falla. El || ejecuta entonces echo ocupado, y es lo único que se imprime.

Un interbloqueo es una espera en círculo

Un cerrojo arregla la carrera, pero crea otro riesgo. Si el proceso A tiene el cerrojo 1 y espera el 2, y B tiene el 2 y espera el 1, ninguno avanza nunca. Es un interbloqueo.

Para dibujarlo se usa el grafo de espera: una flecha de cada proceso al proceso que tiene lo que él espera. Un interbloqueo es un ciclo de flechas.

D espera, pero no está en el ciclo

A espera a B, B espera a C y C espera a A: ese ciclo es un interbloqueo y ninguno de los tres saldrá solo.

D espera a A, así que también está parado. Pero D no forma parte del ciclo: si se rompiera, D seguiría. Para romperlo hay que terminar uno de los tres procesos o quitarle lo que tiene.

Las cuatro condiciones del interbloqueo

CondiciónQué significaCómo se rompe
Exclusión mutuaUn recurso lo usa uno soloCompartirlo, si se puede
Retener y esperarSe espera otro recurso sin soltar el actualPedirlos todos de una vez
Sin expropiaciónNadie puede quitar un recursoPermitir quitarlo
Espera circularLos procesos forman un cicloPedir los cerrojos siempre en el mismo orden

Las celdas que rellenan los estudiantes quedan en blanco en esta vista previa.

Un error frecuente

Advertencia

Mucha gente cree que un programa bloqueado va solo muy lento. Un interbloqueo no va lento: no avanza y no gasta procesador. Esperar más no lo arregla. Hay que romper el ciclo, y lo mejor es evitarlo pidiendo los cerrojos en un orden fijo.

Sobre este laboratorio y su código: Laboratorio de comandos de Linux de cada día: los treinta comandos que se escriben de memoria

¿Enseñas a una clase? Asigna este módulo a tus alumnos con guía del profesor, tareas con corrección automática y un laboratorio para cada alumno.