Dining Philosophers
Dijkstra's solution: always lock the lower-numbered fork first to prevent deadlock.
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Philosopher struct {
name string
leftFork int
rightFork int
}
func (p Philosopher) dine(forks map[int]*sync.Mutex, wg *sync.WaitGroup) {
defer wg.Done()
first, second := p.leftFork, p.rightFork
if first > second {
first, second = second, first
}
for i := 0; i < 3; i++ {
fmt.Printf("%s is thinking\n", p.name)
time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) // simulate thinking
forks[first].Lock()
forks[second].Lock()
fmt.Printf("%s is eating (round %d)\n", p.name, i+1)
time.Sleep(time.Duration(rand.Intn(100)) * time.Millisecond) // simulate eating
forks[second].Unlock()
forks[first].Unlock()
}
fmt.Printf("%s is done\n", p.name)
}
func main() {
forks := make(map[int]*sync.Mutex)
for i := 0; i < 5; i++ {
forks[i] = &sync.Mutex{}
}
philosophers := []Philosopher{
{"Plato", 4, 0},
{"Socrates", 0, 1},
{"Aristotle", 1, 2},
{"Pascal", 2, 3},
{"Locke", 3, 4},
}
var wg sync.WaitGroup
for _, p := range philosophers {
wg.Add(1)
go p.dine(forks, &wg)
}
wg.Wait()
fmt.Println("everyone finished")
}