Reputation: 8087
I have this program:
package main
import (
"fmt"
"time"
)
var ch1 = make(chan int)
var ch2 = make(chan int)
func f1() {
select {
case <-ch1:
fmt.Println("ch1")
}
}
func f2() {
select {
case <-ch2:
fmt.Println("ch2")
}
}
func main() {
go f1()
go f2()
time.Sleep(2 * time.Second)
fmt.Println("no buffered channel will wait?")
ch1 <- 1
ch2 <- 2
fmt.Println("main exits")
}
I expect that, as long as f1 and f2 doesn't print anything, it means ch1 and ch2 has nothing inside, so ch1<-1
and ch2<-2
should block?
But when run, it prints:
no buffered channel will wait?
main exits
Why those unbuffered channels ch1
and ch2
were not blocked within main?
If I don't call f1
/f2
in main
, it will report a dead lock
error.
I don't understand what f1/f2 have done to ch1/ch2.
Would you kindly help to explain their behavior?
Upvotes: 0
Views: 342
Reputation: 418455
Both f1()
and f2()
have receive operations. These are blocking operations: as long as there is nobody sending anything on the channel, they wait.
So you launch f1()
and f2()
as new goroutines, and main()
sleeps. Meanwhile f1()
and f2()
are waiting for data from ch1
and ch2
.
Then main()
wakes up, and tries to send a value on ch1
. This is OK because there is a goroutine ready to receive from it (f1()
). Then main()
tries to send on ch2
, this is also OK, there is f2()
ready to receive from it.
Then main()
returns, and app ends (it does not wait for the other goroutines to print).
If you don't launch f1()
and f2()
as new goroutines, when main()
reaches the send statements, there will be nobody ready to receive from the channels, and since it is unbuffered, it will block. And since there won't be any more goroutines running, this is a deadlock.
Upvotes: 7