Visualización interactiva del problema clásico de sincronización
Espacios disponibles para producir
Elementos disponibles para consumir
El problema del Productor-Consumidor es un clásico de la programación concurrente donde:
⚠️ Desafío: Sincronizar el acceso para evitar que el productor escriba en un buffer lleno o que el consumidor lea de un buffer vacío.
Se utilizan dos semáforos para coordinar el acceso:
Cuenta los espacios disponibles para producir. Inicia en
BUFFER_SIZE (8).
Cuenta los elementos disponibles para consumir. Inicia en
0.
📐 Invariante:
semVacíos + semLlenos = BUFFER_SIZE (siempre 8)
wait(semVacíos)
Si semVacíos = 0, el productor se bloquea hasta que haya espacio.
lock(mutex)
Garantiza acceso exclusivo al buffer.
buffer[head] = valor
head = (head + 1) % BUFFER_SIZE
Escribe el dato y avanza el índice de forma circular.
unlock(mutex)
Libera el acceso al buffer.
signal(semLlenos)
Incrementa semLlenos, notificando al consumidor.
wait(semLlenos)
Si semLlenos = 0, el consumidor se bloquea hasta que haya datos.
lock(mutex)
Garantiza acceso exclusivo al buffer.
valor = buffer[tail]
tail = (tail + 1) % BUFFER_SIZE
Lee el dato y avanza el índice de forma circular.
unlock(mutex)
Libera el acceso al buffer.
signal(semVacíos)
Incrementa semVacíos, notificando al productor.
El productor nunca escribe en un buffer lleno gracias a semVacíos.
El consumidor nunca lee de un buffer vacío gracias a semLlenos.
Solo un hilo accede al buffer a la vez mediante la sección crítica.
El orden de adquisición de recursos previene interbloqueos.
| Paso | Acción | semVacíos | semLlenos | Buffer |
|---|---|---|---|---|
| 0 | Estado inicial | 8 | 0 | [ , , , , , , , ] |
| 1 | Productor escribe 1 | 7 | 1 | [1, , , , , , , ] |
| 2 | Productor escribe 2 | 6 | 2 | [1,2, , , , , , ] |
| 3 | Consumidor lee 1 | 7 | 1 | [ ,2, , , , , , ] |
| 4 | Productor escribe 3 | 6 | 2 | [ ,2,3, , , , , ] |
| 5 | Consumidor lee 2 | 7 | 1 | [ , ,3, , , , , ] |
💡 Nota: Observa cómo la suma de semVacíos + semLlenos siempre es 8.