如果我传递超过 12 个totalValues
到getResults()
,则不会从通道resultCh
读取任何值,我得到fatal error: all goroutines are asleep - deadlock!
:
package main
type result struct {
index int
count int
}
func getResults(indexCh chan int, resultCh chan result, totalValues int) {
allFields := make([]int, totalValues)
for i := range allFields {
indexCh <- i
println("Sent value", i)
}
println("Sent all values")
for i := 0; i < totalValues; i++ {
value := <-resultCh
println("Received result", value.index)
allFields[value.index] = value.count
}
println("Done processing")
}
func processValue(indexCh chan int, ch chan result) {
for index := range indexCh {
println("Received value", index)
ch <- result{
index: index,
count: index * index,
}
println("Sent result", index)
}
}
func main() {
bufferDepth := 4
indexCh := make(chan int, bufferDepth)
resultCh := make(chan result, bufferDepth)
for i := 0; i < 4; i++ {
go processValue(indexCh, resultCh)
}
// Value > 12 results in goroutine asleep
getResults(indexCh, resultCh, 12)
}
上面的代码通过使用从缓冲通道indexCh
读取值的函数processValue()
启动四个goroutine来工作。整数 0 到totalValues
按getResults()
插入到indexCh
中。processValue()
处理该值并将结果放入缓冲通道resultCh
,由getResults()
读取。
我只在totalValues
大于 12 时才观察到这个问题。不会从resultCh
读取任何值,因为"收到的结果..."未打印。
如果我将bufferDepth
增加到 5,则程序成功完成 12totalValues
>和 15 <。
如果resultCh
的缓冲区深度与totalValues
匹配,则程序也会成功完成。
getResults
首先将所有值写入通道。有 4 个 goroutines 在侦听,因此每个 goroutines 都会拾取这些值,并且它们被阻止写入结果通道。通道的缓冲区大小为 4。因此,4 个 goroutines 每个程序可以在阻塞之前将总共 4 个值写入结果通道。
4 个 goroutines + 4 个索引通道大小 + 4 个结果通道大小 = 12 个条目
之后,processValue
在写入通道时被阻止,因为getResults
也被阻止写入indexCh
。