// 生产者和消费者出现在同一个 goroutine 中 func f3() { ch := make(chan int) // producer blocked the routine, consumer has no opportunity to run ch <- 1 // this line not able to reach <-ch
} func main() { f3() }
result:
1 2 3 4 5 6 7 8 9 10
fatal error: all goroutines are asleep - deadlock!
all producers are stucked, because consumers quit too early. groutine number increase from 1 to 11.
just change this line:
1
case <-time.After(2500 * time.Millisecond):
result:
1 2 3 4 5 6 7 8 9 10 11 12
before goroutine num: 1 result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) result : %!n(int=100) after goroutine num: 1
before goroutine num: 1 result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist result : 1 result : 2 producer exist after goroutine num: 11
this happens because of this code:
1 2 3
for result := range ch { fmt.Printf("result : %d\n", result) }
for …. range code is blocking consumer, to fix this bug, we need to close channel
before goroutine num: 1 result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel result : 1 result : 2 producer close channel after goroutine num: 1
funcmain() { fooVal := make(chanint) for i := 0; i < 10; i++ { wg.Add(1) go foo(fooVal, i)
}
wg.Wait() // Wait for all routines to complete close(fooVal) // close channel
for item := range fooVal { fmt.Println(item) } }
at line 25, wg.Wait is blocking, waiting for subroutine create at line 14. but fooVar is an unbuffered channel, so at line 14, c <- someValue * 5 is also a blocking call. only when channel has consumer to consume, then goroutine foo be able to resume and do wg.Done. but problem is the for .. range fooVar is after wg.Wait, the execution is stucked at wg.Wait not able to move forward, so wg is wating for foo, foo is waiting for wg, deadlock happens.
solution, make fooVal a buffered channel with size 10.