英文:
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
.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论