我正在使用通道实现队列的练习中。具体来说,我正在尝试使用通道的大小来限制并行goroutine的数量。出于智慧,我编写了以下代码:package mainimport "fmt"import "time"import "math/rand"func runTask (t string, ch *chan bool) { start := time.Now() fmt.Println("starting task", t) time.Sleep(time.Millisecond * time.Duration(rand.Int31n(1500))) // fake processing time fmt.Println("done running task", t, "in", time.Since(start)) <- *ch}func main() { numWorkers := 3 files := []string{"a", "b", "c", "d", "e", "f", "g", "h", "i", "j"} activeWorkers := make(chan bool, numWorkers) for _, f := range files { activeWorkers <- true fmt.Printf("activeWorkers is %d long.\n", len(activeWorkers)) go runTask(f, &activeWorkers) } select{}}现在,代码崩溃并带有:throw: all goroutines are asleep - deadlock!我的期望是对select的调用将永远阻塞,并使goroutine在没有死锁的情况下终止。所以我有两个问题:为什么选择不会永远阻塞,并且没有在time.Sleep()中抛出,在for循环之后调用,如何避免死锁?
3 回答
牧羊人nacy
TA贡献1862条经验 获得超7个赞
tux21b已经发布了一个更惯用的解决方案,但是我想以另一种方式回答您的问题。select {}会永远阻止,是的。当所有goroutine被阻止时,将发生死锁。如果其他所有goroutine完成,则只剩下被阻塞的主goroutine,这是一个死锁。
通常,您希望在所有其他goroutine完成之后在主goroutine中执行某些操作,要么使用它们的结果,要么只是进行清理,为此您将执行tux21b的建议。如果您真的只是想让main完成,而让其余goroutine继续工作,请放在defer runtime.Goexit()
main函数的顶部。这将导致它退出而不退出程序。
- 3 回答
- 0 关注
- 226 浏览
添加回答
举报
0/150
提交
取消