英文:
Channel not receiving any values if sending to many values
问题
如果我将totalValues传递给getResults()的值设为大于12,那么从通道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("发送值", i)
}
println("发送所有值")
for i := 0; i < totalValues; i++ {
value := <-resultCh
println("接收结果", value.index)
allFields[value.index] = value.count
}
println("处理完成")
}
func processValue(indexCh chan int, ch chan result) {
for index := range indexCh {
println("接收值", index)
ch <- result{
index: index,
count: index * index,
}
println("发送结果", 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)
}
// 当totalValues > 12时,出现goroutine休眠的问题
getResults(indexCh, resultCh, 12)
}
上述代码通过使用函数processValue()启动四个goroutine来工作,这些goroutine从缓冲通道indexCh中读取值。整数0到totalValues被插入到indexCh中,由getResults()函数完成。processValue()函数处理该值,并将结果放入缓冲通道resultCh中,然后由getResults()函数读取。
只有当totalValues大于12时,我才会观察到这个问题。因为没有从resultCh中读取任何值,所以不会打印出"Received result..."。
如果我将bufferDepth增加到5,那么对于totalValues大于12且小于15的情况,程序将成功完成。
如果resultCh的缓冲区深度与totalValues匹配,程序也将成功完成。
英文:
If I pass more than 12 for totalValues to getResults(), no values are read from channel resultCh and I get 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)
}
The above code works by launching four goroutines using function processValue() that read values from buffered channel indexCh. Integers 0 to totalValues are inserted into indexCh by getResults(). processValue() processes the value and puts the result onto buffered channel resultCh, which is read by a getResults().
I only only observe this problem when totalValues is greater than 12. No values are read from resultCh because "Received result..." is not printed.
If I increase bufferDepth to five, the program completes successfully for totalValues > 12 and < 15.
The program also completes successfully if the buffer depth of resultCh matches totalValues.
答案1
得分: 2
getResults首先将所有的值写入通道。有4个goroutine在监听,所以每个goroutine都会接收这些值,并且它们在写入结果通道时被阻塞。通道的缓冲区大小为4。因此,在被阻塞之前,每个goroutine可以将4个值写入结果通道。
4个goroutine + 4个索引通道大小 + 4个结果通道大小 = 12个条目
之后,processValue在写入通道时被阻塞,因为getResults也在写入indexCh时被阻塞。
英文:
getResults starts by writing all values to the channel. There are 4 goroutines listening, so each picks up those values, and they are blocked writing to the result channel. Channels have buffer sizes of 4. So 4 goroutines each can write a total of 4 values to result channel before blocking.
4 goroutines + 4 index channel size + 4 result channel size = 12 entries
After that, the processValue is blocked at writing to the channel, because getResults are also blocked writing to the indexCh.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论