Reputation: 39
I wanna use setter function to send 0-9 into ch1 channel ,and computer function square the number from ch1, then send the result into ch2 channel . however, i get panic when running this code. would anybody explain why this situation happened, i totally confused.
package main
import (
"fmt"
"sync"
)
func setter(ch1 chan int, wg sync.WaitGroup) {
for i:= 0; i< 10;i++ {
fmt.Println("setter:", i)
ch1 <- i
}
close(ch1)
wg.Done()
}
func computer(ch1 chan int, ch2 chan int, wg sync.WaitGroup) {
for true {
tmp, ok := <- ch1
if !ok {
fmt.Println("computer: there is no value in ch1")
break
}
fmt.Println("computer:", tmp*tmp)
ch2 <- tmp*tmp
}
close(ch2)
wg.Done()
}
func main(){
ch1 := make(chan int,1)
ch2 := make(chan int,1)
var wg sync.WaitGroup
wg.Add(2)
go setter(ch1, wg)
go computer(ch1, ch2, wg)
wg.Wait()
}
the error like this :
setter: 0
setter: 1
setter: 2
computer: 0
computer: 1
setter: 3
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc000196008)
/usr/local/go/src/runtime/sema.go:56 +0x45
sync.(*WaitGroup).Wait(0xc000196000)
/usr/local/go/src/sync/waitgroup.go:130 +0x65
main.main()
/Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:50 +0x13b
goroutine 18 [chan send]:
main.setter(0xc000194000, 0x200000000, 0xc000000000)
/Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:16 +0x107
created by main.main
/Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:47 +0xdb
goroutine 19 [chan send]:
main.computer(0xc000194000, 0xc000194070, 0x200000000, 0x0)
/Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:35 +0x11c
created by main.main
/Users/koujianyuan/Desktop/code/project/go/chan/communication/demo.go:48 +0x12d
Upvotes: 0
Views: 378
Reputation: 4324
The reason why there is a deadlock is that you are not reading from the ch2
channel. The ch2
channel block when you try to put the value in it for the second time (the first time it passes because it is a buffered channel of 1). When putting the value in the ch2
channel blocks, it also blocks reading the value from the ch1
channel, so the setter
goroutine cannot put values in ch1
anymore.
With both ch1
and ch2
channels blocked, both setter
and computer
goroutines cannot finish, which causes a deadlock.
Here is a working example. I've added the reader
function that read from the ch2
channel.
// The rest of the code is the same except I've changed the functions to use *sync.Waitgroup
func reader(ch chan int, wg *sync.WaitGroup) {
defer wg.Done()
for i := range ch {
fmt.Println("reading from channel", i)
}
fmt.Println("reader exiting")
}
func main() {
ch1 := make(chan int, 1)
ch2 := make(chan int, 1)
var wg sync.WaitGroup
wg.Add(3)
go reader(ch2, &wg)
go setter(ch1, &wg)
go computer(ch1, ch2, &wg)
wg.Wait()
}
Upvotes: 1