#!/usr/bin/env python3
"""
Demostración del interbloqueo (deadlock) clásico en el problema de los filósofos comensales.
Solución simétrica: cada filósofo intenta tomar primero su palillo izquierdo y luego el derecho.
Al sincronizarse o introducir una pequeña pausa, todos los filósofos adquieren su palillo izquierdo
simultáneamente y quedan bloqueados indefinidamente esperando el derecho (espera circular).
"""

import threading
import time

PHILOSOPHERS = 5

class Philosopher(threading.Thread):
    forks = [threading.Lock() for _ in range(PHILOSOPHERS)]

    def __init__(self, pid):
        super().__init__()
        self.pid = pid

    def left_fork(self):
        return self.pid

    def right_fork(self):
        return (self.pid + 1) % PHILOSOPHERS

    def think(self):
        time.sleep(0.05)

    def pick(self):
        # Todos toman primero el palillo izquierdo (simetría)
        print(f"Filósofo {self.pid} toma palillo izquierdo ({self.left_fork()})...")
        Philosopher.forks[self.left_fork()].acquire()

        # Pequeña pausa que fuerza la condición de carrera hacia el interbloqueo
        time.sleep(0.05)

        print(f"Filósofo {self.pid} intenta tomar palillo derecho ({self.right_fork()})...")
        Philosopher.forks[self.right_fork()].acquire()
        print(f" Filósofo {self.pid} tiene ambos palillos y puede comer!")

    def eat(self):
        print(f"Filósofo {self.pid} comiendo...")
        time.sleep(0.1)

    def release(self):
        Philosopher.forks[self.left_fork()].release()
        Philosopher.forks[self.right_fork()].release()
        print(f"Filósofo {self.pid} suelta ambos palillos.")

    def run(self):
        self.think()
        self.pick()
        self.eat()
        self.release()

def main():
    print("=== Demostración de Deadlock (Espera Circular) en Filósofos ===")
    print("Iniciando 5 filósofos que adquieren primero el palillo izquierdo...")
    threads = [Philosopher(i) for i in range(PHILOSOPHERS)]
    for t in threads:
        t.start()

    time.sleep(1.5)
    print("\n[ALERTA DE DEADLOCK] Todos los filósofos tienen su palillo izquierdo y esperan el derecho.")
    print("Ninguno puede avanzar ni soltar su palillo (Condiciones de Coffman cumplidas).")

if __name__ == "__main__":
    main()
