Concurrency GoLang教程中的死锁错误
我正在尝试做这个教程- 这是我的密码Concurrency GoLang教程中的死锁错误,concurrency,go,Concurrency,Go,我正在尝试做这个教程- 这是我的密码 // 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 { Walk(t.Left, ch) ch <- t.Value Walk(t.Right,ch) } } // Same d
// 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 {
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 {
ch1 := make(chan int)
ch2 := make(chan int)
go Walk(t1, ch1)
go Walk(t2, ch2)
for i:= range ch1 {
if i != <-ch2 {
return false
}
}
return true
}
func main() {
isSame := Same(tree.New(1), tree.New(1))
if isSame {
fmt.Println("SAME")
} else {
fmt.Println("DIFF")
}
}
它工作了一次,然后我又运行了一次,它停止了工作……要么就是这样,要么就是我疯了
发生了什么事?问题是您从未关闭
ch1
,因此您的for i:=range ch1
循环永远不会结束;它只是读取,直到通道中没有值,然后阻塞。此时,将只有一个goroutine,并且它在侦听空通道时被阻止,因此Go将中止并显示您看到的消息。(类似地,您从不关闭ch2
,但在您的情况下,这并不重要。如果ch2
的值小于ch1
,则会导致死锁。)
老实说,我不确定“围棋之旅”的人到底想了什么解决方案
一个可行但完全是欺骗的选项是硬编码这样一个事实,即您只能看到十个值:
for i := 0; i < 10; i++ {
if <-ch1 != <-ch2 {
return false
}
}
(或者你可以使用一个非匿名函数;称它为walkAndClose
或其他什么)
顺便提一下,您的Same
函数假定两棵树的大小相同。如果t1
有更多的元素,那么t2
将在末尾隐式填充零(因为
for i := 0; i < 10; i++ {
if <-ch1 != <-ch2 {
return false
}
}
go func() {
Walk(t1, ch1)
close(ch1)
}()
for i := range ch1 {
j, receivedJ := <-ch2
if i != j || ! receivedJ {
return false
}
}
_, receivedJ := <-ch2
if receivedJ {
return false
}