package main import ( "fmt" "math/rand" "sync" "time" ) const ( bites = 3 delay = 3 ) var philo = []string{ "Aristotle", "Kant", "Spinoza", "Marx", "Russell", } type Philo struct { Name string LHS chan bool RHS chan bool Bites int } func rndDelay() { n := time.Duration(rand.Intn(delay) + 1) time.Sleep(n * time.Second) } func (p Philo) state(s string) { fmt.Printf("%10s %s\n", p.Name, s) } type stateFn func(*Philo) stateFn func arrive(p *Philo) stateFn { p.state("arrives") return hungry } func hungry(p *Philo) stateFn { p.state("is hungry") <-p.LHS // grab a fork <-p.RHS // grab a fork return eat } func eat(p *Philo) stateFn { p.state("is eating") rndDelay() p.LHS <- true // release a fork p.RHS <- true // release a fork if p.Bites -= 1; p.Bites <= 0 { return leave } return think } func think(p *Philo) stateFn { p.state("is thinking") rndDelay() return hungry } func leave(p *Philo) stateFn { p.state("leaves") return nil } func prepare(n int) []chan bool { forks := make([]chan bool, n) for i := range forks { forks[i] = make(chan bool, 1) forks[i] <- true // put a fork } return forks } func init() { now := time.Now().Unix() rand.Seed(now) } func main() { fmt.Println(len(philo), "philosophers dining") defer fmt.Println("Table is empty") forks := prepare(len(philo)) wg := sync.WaitGroup{} defer wg.Wait() for i, name := range philo { wg.Add(1) p := &Philo{ Name: name, LHS: forks[i], RHS: forks[(i+1)%len(philo)], Bites: bites, } go func(p *Philo) { defer wg.Done() for state := arrive; state != nil; { state = state(p) } }(p) } }