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
.
CodePudding user response:
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
.