🔄 Productor-Consumidor con Semáforos

Visualización interactiva del problema clásico de sincronización

5x
🏭

Productor

Esperando
-

Buffer Circular (8 posiciones)

HEAD
TAIL
🔒
Sección Crítica
🏪

Consumidor

Esperando
-

Semáforo Vacíos

8 / 8

Espacios disponibles para producir

Semáforo Llenos

0 / 8

Elementos disponibles para consumir

📊 Estadísticas

Producidos: 0
Consumidos: 0
En Buffer: 0

📝 Registro de Actividad

Sistema inicializado. Presiona "Iniciar" para comenzar.

📚 ¿Cómo funciona el algoritmo Productor-Consumidor con 2 Semáforos?

🎯 El Problema

El problema del Productor-Consumidor es un clásico de la programación concurrente donde:

  • Productor: Genera datos y los coloca en un buffer compartido
  • Consumidor: Extrae datos del buffer y los procesa
  • Buffer: Espacio limitado compartido entre ambos

⚠️ 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.

🔐 Solución con 2 Semáforos

Se utilizan dos semáforos para coordinar el acceso:

semVacíos

Cuenta los espacios disponibles para producir. Inicia en BUFFER_SIZE (8).

semLlenos

Cuenta los elementos disponibles para consumir. Inicia en 0.

📐 Invariante: semVacíos + semLlenos = BUFFER_SIZE (siempre 8)

🏭 Algoritmo del Productor

1
Esperar espacio disponible wait(semVacíos)

Si semVacíos = 0, el productor se bloquea hasta que haya espacio.

2
Entrar a sección crítica lock(mutex)

Garantiza acceso exclusivo al buffer.

3
Producir y escribir buffer[head] = valor head = (head + 1) % BUFFER_SIZE

Escribe el dato y avanza el índice de forma circular.

4
Salir de sección crítica unlock(mutex)

Libera el acceso al buffer.

5
Señalar elemento disponible signal(semLlenos)

Incrementa semLlenos, notificando al consumidor.

🏪 Algoritmo del Consumidor

1
Esperar elemento disponible wait(semLlenos)

Si semLlenos = 0, el consumidor se bloquea hasta que haya datos.

2
Entrar a sección crítica lock(mutex)

Garantiza acceso exclusivo al buffer.

3
Leer y consumir valor = buffer[tail] tail = (tail + 1) % BUFFER_SIZE

Lee el dato y avanza el índice de forma circular.

4
Salir de sección crítica unlock(mutex)

Libera el acceso al buffer.

5
Señalar espacio disponible signal(semVacíos)

Incrementa semVacíos, notificando al productor.

✨ Propiedades Garantizadas

🚫

No Overflow

El productor nunca escribe en un buffer lleno gracias a semVacíos.

🚫

No Underflow

El consumidor nunca lee de un buffer vacío gracias a semLlenos.

🔒

Exclusión Mutua

Solo un hilo accede al buffer a la vez mediante la sección crítica.

Sin Deadlock

El orden de adquisición de recursos previene interbloqueos.

🔄 Ejemplo de Ejecución

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.