Hi, I am playing with Tour of Go exercise Equivalent Binary Trees. I have completed the code but I notice something strange:
package main
import "golang.org/x/tour/tree"
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan<- int) {
if t == nil {
return
}
Walk(t.Left, ch)
ch <- t.Value
Walk(t.Right, ch)
}
// Same determines whether the trees
// t1 and t2 contain the same values.
func Same(t1, t2 *tree.Tree) bool {
c1 := make(chan int)
c2 := make(chan int)
go func() {
Walk(t1, c1)
close(c1)
}()
go func() {
Walk(t2, c2)
close(c2)
}()
for i := range c1 {
if i != <-c2 {
return false
}
}
return true
}
func main() {
println(Same(tree.New(10), tree.New(10)))
}
As can be seen, in the Same method, if I use the following equivalent code instead, then deadlock will arise. Can someone help me explain this problem? Thanks
go func() {
Walk(t1, c1)
close(c1)
Walk(t2, c2)
close(c2)
}()
Your main goroutine receives the first value from c1 in the for ā¦ range loop
Your main goroutine attempts a receive from c2 to compare it to the value from c1.
Your āwalker goroutineā hasnāt returned from Walk(t1, c1) yet, so Walk(t2, c2) hasnāt started. Nothing is getting sent into c2, so receiving from it will deadlock.
main and go1 all blocked.
main need recv ch1 and ch2, but not recv ch2. go1 not send value to c2 in block state, so main revc c2 in block state,all goroutine to blocked state.
g1 need c1 send 10ci value 10-100, then c2 send 10ci.
main need recv c1 then recv c2 Repeat 10ci.
but g1 send ā20ā main is blocked state wait revc c2,so g1 and main in blocked, if c1 and c2 cap is 10,then not blocked.
Thanks. I somehow get it. But I have one more question: Why āsend 20ā must wait for range to pop it out? I mean, from my point of view, it is in a different thread, so why canāt we just put to channel independently?
it is in a different goroutine, Chan is essentially a blocking queue with a lock.
chan accepts a value that is blocked if there is no data, and sends a value that is also blocked if chan is full.