Permalink
Browse files

toy concurrency problem implemented in go

  • Loading branch information...
0 parents commit 9085e433672a261e6590cbdbf0c18aed113f43a5 @doug committed Jan 8, 2011
Showing with 102 additions and 0 deletions.
  1. +2 −0 .gitignore
  2. +6 −0 Makefile
  3. +94 −0 dining-philosophers.go
@@ -0,0 +1,2 @@
+*.6
+dinnerparty
@@ -0,0 +1,6 @@
+include $(GOROOT)/src/Make.inc
+
+TARG=dinnerparty
+GOFILES=dining-philosophers.go
+
+include $(GOROOT)/src/Make.cmd
@@ -0,0 +1,94 @@
+/**
+* Toy Go implementation of Dining Philosophers problem
+* http://en.wikipedia.org/wiki/Dining_philosophers_problem
+* Author: Doug Fritz
+* Date: 2011-01-05
+**/
+
+package main
+
+import (
+ "fmt"
+ "rand"
+ "time"
+)
+
+type Philosopher struct {
+ id int
+ name string
+ chopstick chan bool
+ neighbor *Philosopher
+}
+
+func makePhilosopher(id int, name string, neighbor *Philosopher) *Philosopher {
+ phil := &Philosopher{id, name, make(chan bool, 1), neighbor}
+ phil.chopstick <- true
+ return phil
+}
+
+func (phil *Philosopher) think() {
+ fmt.Printf("%v is thinking.\n",phil.name)
+ time.Sleep(rand.Int63n(1e9))
+}
+
+func (phil *Philosopher) eat() {
+ fmt.Printf("%v is eating.\n", phil.name)
+ time.Sleep(rand.Int63n(1e9))
+}
+
+func (phil *Philosopher) getChopsticks() {
+ timeout := make(chan bool, 1)
+ go func() { time.Sleep(1e9); timeout <- true }()
+ select {
+ case <-phil.chopstick:
+ fmt.Printf("%v got his chopstick.\n",phil.name)
+ select {
+ case <-phil.neighbor.chopstick:
+ fmt.Printf("%v got %v's chopstick.\n",phil.name,phil.neighbor.name)
+ fmt.Printf("%v has two chopsticks.\n",phil.name)
+ return
+ case <-timeout:
+ phil.chopstick <- true
+ phil.think()
+ phil.getChopsticks()
+ }
+ case <-timeout:
+ phil.think()
+ phil.getChopsticks()
+ }
+}
+
+func (phil *Philosopher) returnChopsticks() {
+ phil.chopstick <- true
+ phil.neighbor.chopstick <- true
+}
+
+func (phil *Philosopher) dine(announce chan *Philosopher) {
+ phil.think()
+ phil.getChopsticks()
+ phil.eat()
+ phil.returnChopsticks()
+ announce <- phil
+}
+
+func main() {
+ names := []string{"Kant","Heidegger","Wittgenstein",
+ "Locke","Descartes","Newton","Hume","Leibniz"}
+ philosophers := make([]*Philosopher,len(names))
+ var phil *Philosopher
+ for i, name := range names {
+ phil = makePhilosopher(i,name,phil)
+ philosophers[i] = phil
+ }
+ philosophers[0].neighbor = phil
+ fmt.Printf("There are %v philosophers sitting at a table.\n", len(philosophers))
+ fmt.Println("They each have one chopstick, and must borrow from their neighbor to eat.")
+ announce := make(chan *Philosopher)
+ for _, phil := range philosophers {
+ go phil.dine(announce)
+ }
+ for i :=0; i<len(names); i++ {
+ phil := <-announce
+ fmt.Printf("%v is done dining.\n",phil.name)
+ }
+}

0 comments on commit 9085e43

Please sign in to comment.