blob: bb44f7b8b7166bd6bd16e1faa2025a0b9191328f (
plain) (
blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
|
package main
import (
"fmt"
"runtime"
)
type philosopher struct {
i int
forks [2]chan bool
eating chan int
done chan struct{}
}
func (p philosopher) run() {
for {
select {
case <-p.done:
return
case <-p.forks[0]:
p.eat()
}
}
}
func (p philosopher) eat() {
select {
case <-p.done:
return
case <-p.forks[1]:
p.eating <- p.i
p.forks[0] <- true
p.forks[1] <- true
runtime.Gosched()
}
}
func startPhilosophers(n int) (chan struct{}, chan int) {
philosophers := make([]*philosopher, n)
chans := make([]chan bool, n)
for i := range chans {
chans[i] = make(chan bool, 1)
chans[i] <- true
}
eating := make(chan int, n)
done := make(chan struct{})
for i := range philosophers {
var min, max int
if i == n - 1 {
min = 0
max = i
} else {
min = i
max = i + 1
}
philosophers[i] = &philosopher{i: i, forks: [2]chan bool{chans[min], chans[max]}, eating: eating, done: done}
go philosophers[i].run()
}
return done, eating
}
func wait(c chan int) {
fmt.Println(<- c)
runtime.Gosched()
}
func main() {
// Restrict go to 1 real thread so we can be sure we're seeing goroutines
// and not threads.
runtime.GOMAXPROCS(1)
// Create a bunch of goroutines
done, eating := startPhilosophers(20) // stop1
// Now turn up the number of threads so this goroutine is likely to get
// scheduled on a different thread.
runtime.GOMAXPROCS(runtime.NumCPU()) // stop2
// Now let things run. Hopefully we'll bounce around
wait(eating)
wait(eating)
wait(eating)
wait(eating)
wait(eating)
wait(eating)
wait(eating)
wait(eating)
wait(eating)
wait(eating)
close(done)
fmt.Println("done") // stop3
}
|