# Problema dei filosofi a cena

Il problema dei filosofi a cena, altrimenti noto come problema dei cinque filosofi, è un esempio che illustra un comune problema di controllo della concorrenza in informatica. Si tratta di un classico problema di sincronizzazione fra processi paralleli.

## Descrizione

L'esempio fu descritto nel 1965 da Edsger Dijkstra, che se ne servì per esporre un problema di sincronizzazione. Cinque filosofi siedono ad una tavola rotonda con un piatto di spaghetti davanti e una forchetta a sinistra (o a destra; secondo un'altra versione vi è invece un bastoncino cinese). Ci sono dunque cinque filosofi, cinque piatti di spaghetti e cinque forchette.
Si immagini che la vita di un filosofo consista di periodi alterni di mangiare e pensare, e che ciascun filosofo abbia bisogno di due forchette per mangiare, ma che le forchette vengano prese una per volta. Dopo essere riuscito a prendere due forchette il filosofo mangia per un po', poi lascia le forchette e ricomincia a pensare. Il problema consiste nello sviluppo di un algoritmo che impedisca lo stallo (deadlock) o la morte d'inedia (starvation). Il deadlock può verificarsi se ciascuno dei filosofi tiene in mano una forchetta senza mai riuscire a prendere l'altra. Il filosofo F$_1$ aspetta di prendere la forchetta che ha in mano il filosofo F$_2$, che aspetta la forchetta che ha in mano il filosofo F$_3$, e così via in un circolo vizioso. La situazione di starvation può verificarsi indipendentemente dal deadlock se uno dei filosofi non riesce mai a prendere entrambe le forchette.
La presa di forchette è analoga al blocco di risorse limitate nella programmazione reale, situazione nota con il nome di "concorrenza". Bloccare una risorsa è una tecnica comune per garantirne l'accesso da parte di un programma solo o di una sola porzione di programma alla volta. Se la risorsa richiesta da un programma è già stata bloccata, il programma aspetta fino a quando la risorsa si sblocca. Se il blocco coinvolge più di una risorsa, è possibile che in alcune circostanze si verifichi un deadlock. Come esempio si consideri il caso di un programma che ha bisogno di due file da elaborare. Se due programmi di questo genere bloccano un file ciascuno, entrambi aspetteranno invano che l'altro programma sblocchi l'altro file.

## Soluzione

Una possibile soluzione è quella di numerare le forchette ed esigere che vengano prese in ordine numerico crescente, analogamente ad un caso di allocazione gerarchica delle risorse. In questa soluzione i filosofi sono denominati F$_1$, F$_2$, F$_3$, F$_4$ e F$_5$, mentre le forchette alla loro sinistra sono rispettivamente f$_1$, f$_2$, f$_3$, f$_4$ e f$_5$. Il primo filosofo F$_1$ dovrà prendere la prima forchetta f$_1$ prima di poter prendere la seconda forchetta f$_2$. I filosofi F$_2$, F$_3$ e F$_4$ si comporteranno in modo analogo, prendendo sempre la forchetta f$_i$ prima della forchetta f$_{i+1}$. Rispettando l'ordine numerico ma invertendo l'ordine delle mani, il filosofo F$_5$ prenderà prima la forchetta f$_1$ e poi la forchetta f$_5$. Si crea così un'asimmetria che serve ad evitare i deadlock.
L'efficacia nella prevenzione della starvation dipende dal metodo di mutua esclusione utilizzato. Le implementazioni che fanno uso di spinlock, ovvero cicli di attesa, possono provocare starvation a causa di problemi di sincronia inerenti a tali metodi. Altri metodi di mutua esclusione che utilizzano code di attesa possono prevenire la starvation in modo più efficiente assicurando uguale accesso alle forchette da parte di tutti e due i filosofi adiacenti.
Questa soluzione può anche essere generalizzata al caso in cui si voglia consentire ad un qualsiasi numero di agenti di ottenere accesso esclusivo ad un qualsiasi numero di risorse. È necessario che gli agenti si attengano a queste regole:
* Tutti gli agenti devono richiedere accesso alle risorse in ordine crescente, prima cioè di richiedere l'accesso ad una risorsa di ordine maggiore, l'agente deve aver ottenuto l'accesso alle risorse di ordine minore di cui ha bisogno.
* Prima di richiedere l'accesso a una risorsa di ordine minore, l'agente deve rilasciare le risorse di ordine maggiore alle quali sta accedendo.
* Se non ha accesso a una risorsa di ordine maggiore, l'agente deve rilasciare le risorse di ordine minore alle quali sta accedendo.