2 回答

TA貢獻(xiàn)1895條經(jīng)驗(yàn) 獲得超3個(gè)贊
最后一個(gè) goroutine 不會(huì)退出,當(dāng)它寫入通道時(shí),它將在最后一次迭代中被阻止,因?yàn)樗鼪](méi)有消費(fèi)者。沒(méi)有消費(fèi)者的原因是函數(shù)中的選擇情況正在寫入,但沒(méi)有消費(fèi)者,因?yàn)樗诘却蛔x取,所以我們有一個(gè)死鎖。finishEatingChannel
finishEatingChannel
permissionFromHost
permissionChannel<-true
permissionChannel
您可以使權(quán)限從主機(jī)通道緩沖,它將解決此問(wèn)題。
您的代碼中還有一個(gè)錯(cuò)誤,您正在按值傳遞互斥體,這是不允許的

TA貢獻(xiàn)1802條經(jīng)驗(yàn) 獲得超5個(gè)贊
該命令說(shuō)go vet
./main.go:26:13: call of eat copies lock value: sync.Mutex
./main.go:26:30: call of eat copies lock value: sync.Mutex
./main.go:31:34: eat passes lock by value: sync.Mutex
./main.go:31:52: eat passes lock by value: sync.Mutex
另一個(gè)問(wèn)題是,有時(shí) goroutines(哲學(xué)家)在嘗試發(fā)送確認(rèn)時(shí)會(huì)被阻止,因?yàn)樨?fù)責(zé)從此無(wú)緩沖通道讀取數(shù)據(jù)的 goroutine(主機(jī))正忙于嘗試發(fā)送權(quán)限。以下是代碼的確切部分:finishEatingChannel
if ctr<maxEaters {
ctr++
// This goroutine stucks since the last philosopher is not reading from permissionChannel.
// Philosopher is not reading from this channel at is busy trying to write finishEating channel which is not read by this goroutine.
// Thus the deadlock happens.
permissionChannel<-true
}
死鎖是100%可重復(fù)的,當(dāng)只剩下一個(gè)哲學(xué)家需要吃兩次飯時(shí)。
固定版本的代碼:
package main
import (
"fmt"
"math/rand"
"sync"
"time"
)
const (
numOfPhilosophers = 5
numOfMeals = 3
maxEaters = 2
)
func main() {
chopsticks := make([]sync.Mutex, 5)
permissionChannel := make(chan bool)
finishEating := make(chan bool)
go permissionFromHost(permissionChannel, finishEating)
var wg sync.WaitGroup
wg.Add(numOfPhilosophers)
for i := 1; i <= numOfPhilosophers; i++ {
go eat(i, &chopsticks[i-1], &chopsticks[i%numOfPhilosophers], &wg, permissionChannel, finishEating)
}
wg.Wait()
}
func eat(philosopherId int, left *sync.Mutex, right *sync.Mutex, wg *sync.WaitGroup, permissionChannel <-chan bool, finishEatingChannel chan<- bool) {
defer wg.Done()
for i := 1; i <= numOfMeals; i++ {
//lock chopsticks in random order
if RandBool() {
left.Lock()
right.Lock()
} else {
right.Lock()
left.Lock()
}
fmt.Printf("waiting for permission from host %d\n", philosopherId)
<-permissionChannel
fmt.Printf("starting to eat %d (time %d)\n", philosopherId, i)
fmt.Printf("finish to eat %d (time %d)\n", philosopherId, i)
//release chopsticks
left.Unlock()
right.Unlock()
//let host know I am done eating
finishEatingChannel <- true
}
}
func permissionFromHost(permissionChannel chan<- bool, finishEating <-chan bool) {
ctr := 0
for {
if ctr < maxEaters {
select {
case <-finishEating:
ctr--
case permissionChannel <- true:
ctr++
}
} else {
<-finishEating
ctr--
}
}
}
func RandBool() bool {
rand.Seed(time.Now().UnixNano())
return rand.Intn(2) == 1
}
- 2 回答
- 0 關(guān)注
- 113 瀏覽
添加回答
舉報(bào)