5 filosofi sono seduti intorno a un tavolo, e alternano momenti in cui pensano a momenti in cui mangiano. Per mangiare, i filosofi hanno bisogno di due bacchette, ma sul tavolo ne sono disponibili solo 5: ciascun filosofo ne ha una condivisa con il filosofo alla sua destra, e una condivisa con il filosofo alla sua sinistra. Di conseguenza, mentre mangia, i filosofi alla sua destra e sinistra non possono mangiare.
Più precisamente, un filosofo attraversa ciclicamente tre stati:
Una soluzione valida deve fare si che ogni filosofo affamato riesca prima o poi a mangiare, in modo che tutti i filosofi possano continuare all'infinito ad alternare momenti in cui pensano e momenti in cui mangiano.
Nelle istanze concrete di questo problema, i "filosofi" sono processi che competono con altri per delle risorse condivise, le quali possono essere usate solo in mutua esclusione, e ogni processo deve acquisire contemporaneamente più risorse per poter lavorare.
Si usano le seguenti strutture dati:
state
che tiene traccia dello stato del sistema: per ogni filosofo $P_i$, state[i]
può avere valore THINKING, HUNGRY, EATING
mutex
, per la mutua esclusione sull'array state
sem[i]
per ogni filosofo $P_i$, che serve per "dare l'ok" a $P_i$: se $P_i$ non può mangiare (perchè non ha le bacchette), allora si blocca su sem[i]
Ciascun filosofo $P_i$ esegue la procedura philosopher(i)
L'implementazione di think
e eat
non è rilevante per la soluzione del problema
La procedura take_forks
In mutua esclusione, dichiara che $P_i$ ha fame, e chiama la procedura test
per prendere le bacchette se entrambe sono libere:
Se non sono libere entrambe le bacchette, si blocca su sem[i]
(dato che non è stata eseguita la signal all'interno di test
)
La procedura put_forks
viene eseguita interamente in mutua esclusione
Essa: