我刚完成了Coursera(https://www.coursera.org/learn/golang-concurrency/)上的“并发”课程,我为最后的作业感到非常苦恼。这是我的提交:
// 1.There should be 5 philosophers sharing chopsticks, with one chopstick between each adjacent pair of philosophers.
// 2.Each philosopher should eat only 3 times (not in an infinite loop as we did in lecture)
// 3.The philosophers pick up the chopsticks in any order, not lowest-numbered first (which we did in lecture).
// 4.In order to eat, a philosopher must get permission from a host which executes in its own goroutine.
// 5.The host allows no more than 2 philosophers to eat concurrently.
// 6.Each philosopher is numbered, 1 through 5.
// 7.When a philosopher starts eating (after it has obtained necessary locks) it prints “starting to eat <number>” on a line by itself, where <number> is the number of the philosopher.
// 8.When a philosopher finishes eating (before it has released its locks) it prints “finishing eating <number>” on a line by itself, where <number> is the number of the philosopher.
package main
import (
"fmt"
"sync"
)
var eating = make(chan int, 2)
var mu sync.RWMutex
var everyoneAte int
var timesEaten = make(map[int]int, 5)
type chopstick struct {
sync.Mutex
}
type philosopher struct {
leftCs *chopstick
rightCs *chopstick
}
func alreadyAte(index int) bool {
mu.Lock()
defer mu.Unlock()
if timesEaten[index] == 3 {
return true
}
return false
}
func (p philosopher) eat(index int) {
eating <- 1
p.leftCs.Lock()
p.rightCs.Lock()
fmt.Printf("Starting to eat %v\n", index)
fmt.Printf("Finishing eating %v\n", index)
mu.Lock()
timesEaten[index]++
if timesEaten[index] == 3 {
everyoneAte++
}
mu.Unlock()
p.rightCs.Unlock()
p.leftCs.Unlock()
<-eating
}
func main() {
count := 5
chopsticks := make([]*chopstick, count)
for i := 0; i < count; i++ {
chopsticks[i] = &chopstick{}
}
philosophers := make([]*philosopher, count)
for i := 0; i < count; i++ {
philosophers[i] = &philosopher{
leftCs: chopsticks[i],
rightCs: chopsticks[(i+1)%count],
}
}
for {
mu.RLock()
if everyoneAte == count {
return
}
for i := 0; i < count; i++ {
if timesEaten[i] == 3 {
continue
}
go philosophers[i].eat(i + 1)
}
mu.RUnlock()
}
}
我不知道如何实现#4,所以我只是使用了缓冲通道♂️
我不明白为什么一些哲学家回国后吃了超过3次
如果每个人对这些问题都有答案,我将不胜感激。我已经提交了作业。
答案 0 :(得分:1)
这是哲学家进食超过三遍的顺序
假设philosopher_1吃了2次
RLock
timesEaten[1] == 2
philosopher_1
在单独的goroutine_1上吃饭RLock
RLock
timesEaten[1] == 2
philosopher_1
在单独的goroutine_2上再次吃饭RLock
Lock
timesEaten[1] = 3
Lock
Lock
timesEaten[1] = 4
<-philosopher_1
吃了3次以上Lock