The dining philosophers problem, posed by Edsger Dijkstra in 1965, models a classic concurrency hazard: several processes each need two shared resources (here, forks) to make progress, but resources can only be held by one process at a time. Around a round table, each philosopher alternates between thinking and eating, but needs both the fork on their left and the fork on their right to eat.
Deadlock requires four conditions simultaneously: mutual exclusion, hold-and-wait, no preemption, and circular wait. Breaking just one — as resource ordering does to circular wait — is enough to make deadlock structurally impossible, no matter how unlucky the scheduling gets.
Five (or more) philosophers sit at a round table, alternating between thinking and eating, but each needs both the fork to their left and the fork to their right — shared resources that can trigger deadlock or starvation depending on how they're acquired.
Naive "grab left, then right" locking lets every philosopher seize one fork and wait forever for the next — a circular wait that freezes the whole table red. Resource ordering and a waiter/arbitrator strategy both break that cycle and keep meals flowing.
Pick a locking strategy, adjust the number of philosophers and simulation speed, and watch fork colour and philosopher state (grey/yellow/green/red) evolve live. Reset the table to try a fresh run under the same strategy.
Deadlock needs four conditions at once — mutual exclusion, hold-and-wait, no preemption, and circular wait. Breaking just one, as resource ordering does, makes deadlock structurally impossible regardless of scheduling luck.