Skip to content

Instantly share code, notes, and snippets.

@jordanorelli
Created April 7, 2012 21:56
Show Gist options
  • Save jordanorelli/2332384 to your computer and use it in GitHub Desktop.
Save jordanorelli/2332384 to your computer and use it in GitHub Desktop.
dining philosophers
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
type Philosopher struct {
Id int
Left *Fork
Right *Fork
}
type Fork struct {
sync.Mutex
Id int
}
func Seat(numPhilosophers int) []*Philosopher {
zeroFork := &Fork{Id: 0}
prevFork := zeroFork
philosophers := []*Philosopher{}
for i := 0; i < numPhilosophers - 1; i++ {
thisFork := &Fork{Id: i + 1}
philosophers = append(philosophers, &Philosopher{Id: i, Left: prevFork, Right: thisFork})
prevFork = thisFork
}
philosophers = append(philosophers, &Philosopher{Id: numPhilosophers - 1, Left: prevFork, Right: zeroFork})
philosophers[0].Left, philosophers[0].Right = philosophers[0].Right, philosophers[0].Left
return philosophers
}
func (phil *Philosopher) Eat(eating, thinking chan int) {
for {
phil.Right.Lock()
time.Sleep(time.Duration(rand.Int63n(1e7)))
phil.Left.Lock()
eating <- phil.Id
time.Sleep(time.Duration(rand.Int63n(1e8)))
phil.Right.Unlock()
time.Sleep(time.Duration(rand.Int63n(1e7)))
phil.Left.Unlock()
thinking <- phil.Id
time.Sleep(time.Duration(rand.Int63n(1e8)))
}
}
func (phil *Philosopher) String() string {
return fmt.Sprintf("[Philosopher: Id: %d, Left: %d, Right: %d]", phil.Id, phil.Left.Id, phil.Right.Id)
}
func printStatus(thinkCount []int, eatCount []int, mu *sync.Mutex) {
mu.Lock()
for i, val := range thinkCount {
fmt.Print("(", val, ",", eatCount[i], ")", "\t")
}
fmt.Print("\n")
mu.Unlock()
}
func main() {
numPhilosophers := 20
philosophers := Seat(numPhilosophers)
for _, phil := range philosophers {
fmt.Println(phil)
}
eating := make(chan int)
thinking := make(chan int)
for _, phil := range philosophers {
go phil.Eat(eating, thinking)
}
eatCount, thinkCount := make([]int, numPhilosophers), make([]int, numPhilosophers)
writeLock := new(sync.Mutex)
go func() {
for id := range eating {
eatCount[id]++
printStatus(thinkCount, eatCount, writeLock)
}
}()
for id := range thinking {
thinkCount[id]++
printStatus(thinkCount, eatCount, writeLock)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment