gpt4 book ai didi

go - 比赛模拟 fatal error : all goroutines are asleep - deadlock

转载 作者:行者123 更新时间:2023-12-01 22:32:54 26 4
gpt4 key购买 nike

我正在使用 Golang 构建护理模拟,但遇到了死锁问题。
Goroutines 用于代表每个赛车手。
这个想法是,一旦赛车手达到目标,就会使用一个 channel 来传达哪个赛车手获胜。
谁能发现我的错误?

package main

import (
"fmt"
"math/rand"
"strconv"
"sync"
"time"
)

var wg sync.WaitGroup
var counter Counter
var tracks Tracks
var winner chan int

func newCounter(size int) Counter {
return Counter{racers: make([]int, size+1)} // not using the zero'th index
}

func newTracks(size int) Tracks {
return Tracks{racers: make([]string, size+1)}
}

func incrementCounter(n int) {
counter.racers[n]++
}

func equalCounter() bool {
rv := true
for i, _ := range counter.racers {
if counter.racers[0] != counter.racers[i] {
rv = false
break
}
}
return rv
}

func smallerCounter(racerNumber int) bool {
var rv bool
for v := range counter.racers {
if counter.racers[racerNumber] < v {
rv = true
} else {
rv = false
}
}

return rv
}

func checkCounter(racerNumber int) bool {
var rv bool
if equalCounter() || smallerCounter(racerNumber) {
rv = true
} else {
rv = false
}

return rv
}

func racer(racerNum int) {
steps := rand.Intn(5) + 1
distance := 0
goal := 100
if checkCounter(racerNum) {
for j := distance; distance < goal; j++ {
for i := 0; i < steps; i++ {
tracks.racers[racerNum] += "x"
}
distance += steps
duration := rand.Int31n(200)
time.Sleep(time.Duration(duration) * time.Millisecond)
fmt.Println(tracks.racers[racerNum] + "[" + strconv.Itoa(racerNum) + "]")
}

incrementCounter(racerNum)
}

if distance >= goal {
winner <- racerNum
close(winner)
}

wg.Done()
}

func main() {
racers := 5
counter = newCounter(racers)
tracks = newTracks(racers)

for i := 1; i <= racers; i++ {
wg.Add(1)
go racer(i)
}

wg.Wait()

fmt.Print("Winner is:")
fmt.Print(<-winner)
}


type Counter struct {
racers []int
}

type Tracks struct {
racers []string
}


代码也在此处运行:

https://play.golang.org/p/Skr5Es3ItFQ

最佳答案

死锁是因为:

  • 结果 channel 是无缓冲的,因此多次写入将阻塞,因此 wg.Done()从不运行
  • 在所有 5 wg.Done() 之前,没有任何内容从结果 channel 中读取跑(鸡/蛋问题)

  • 快速修复,使结果 channel 缓冲和所有总写入的大小:
    winner = make(chan int, racers)

    https://play.golang.org/p/sbHfOr9YS_z

    channel 也将在 channel 队列中获得所有亚军结果。

    如果您只关心获胜者,则有更有效的方法来满足这种情况,例如创建 referee go-routine 观察第一次写入(获胜者)到结果 channel ,然后取消比赛 context (每个赛车手都会注意上下文取消,一旦宣布一个获胜者,他们就会放弃他们的任务)

    关于go - 比赛模拟 fatal error : all goroutines are asleep - deadlock,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59635575/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com