问题:
I'm not sure what I'm missing but I get a deadlock error. I'm using a buffered channel that I range over after all go routines complete. The channel has the capacity of 4 and I'm running 4 go routines so I'm expecting it to be "closed" automatically once it reaches the max capacity.
package main
import "fmt"
import "sync"
func main() {
ch := make(chan []int, 4)
var m []int
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
defer wg.Done()
ch <- m
return
}()
}
wg.Wait()
for c := range ch {
fmt.Printf("c is %v", c)
}
}
You have two problems :
- there's not enough place for all the goroutines as your channel is too small : when your channel is full, the remaining goroutines must wait for a slot to be freed
range ch
is still waiting for elements to come in the channel and there's no goroutine left to write on it.
Solution 1 :
Make the channel big enough and, close it so that range
stops waiting :
ch := make(chan []int, 5)
...
wg.Wait()
close(ch)
This works but this mostly defeats the purpose of channels here as you don't start printing before all tasks are done.
Solution 2 : This solution, which would allow a real pipelining (that is a smaller channel buffer), would be to do the Done()
when printing :
func main() {
ch := make(chan []int, 4)
var m []int
var wg sync.WaitGroup
for i := 0; i < 5; i++ {
wg.Add(1)
go func() {
ch <- m
return
}()
}
go func() {
for c := range ch {
fmt.Printf("c is %v
", c)
wg.Done()
}
}()
wg.Wait()
}
range
waits until the channel is closed. That's how it works. This way you can launch a goroutine and have it still work if you push elements into the channel later. – Denys Séguret Jul 7 '14 at 12:04wg.Wait()
after the for loop, range over the channel and display the results of each routine. There is no "close(ch)" operation. I can only assume that the program itself goes into deadlock but I don't get the error. – hey Jul 7 '14 at 12:10main
? – hey Jul 7 '14 at 12:13fmt.Printf("c is %v ", c)
play.golang.org/p/Be8eEc6PMu – hey Jul 7 '14 at 12:41