Go 读取永久循环中两个通道的输出

Go 读取永久循环中两个通道的输出,go,Go,我正在做树的练习。我已尝试实现与下面所述相同的功能 func Same(t1, t2 *tree.Tree) bool { ch1 := make(chan int) ch2 := make(chan int) go Walk(t1, ch1); go Walk(t2, ch2); for c := range ch1 { d := <- ch2 if c-d !=0 { return fal

我正在做树的练习。我已尝试实现与下面所述相同的功能

func Same(t1, t2 *tree.Tree) bool {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go Walk(t1, ch1);
    go Walk(t2, ch2);

    for c := range ch1 {
        d := <- ch2
        if c-d !=0 {
            return false
        }   

    }
    return true
}
func-Same(t1,t2*tree.tree)bool{
ch1:=制造(成交量)
ch2:=制造(成交量)
步行(t1,ch1);
步行(t2,ch2);
对于c:=范围ch1{

d:=这里有一个问题,您没有为walk函数中的右子树向通道发送值。但在另一侧接收它,这就是死锁错误的原因。因为您从通道接收到的右子树值从未发送过。

这里有一个问题,您没有为右子树向通道发送值在walk函数中。但在另一端接收它,这就是死锁错误的原因。因为如果右子树从未发送,您将从通道接收一个值。

在遍历树后应关闭通道,以在树相等的情况下终止范围循环(请注意:
Same
在中缀遍历树相等时返回true,不要求它们的结构相等)


注意:如果树的项目数不同,并且没有发现差异,则应检查第二个通道是否已关闭(“线程饥饿”在这里比“死锁”更合适)。如果树相等,则应在遍历树后关闭通道以终止范围循环(请注意:
Same
在中缀遍历树相等时返回true,不要求它们的结构相等)


注意:您应该检查第二个通道是否已关闭,以防树具有不同数量的项,并且没有发现差异(“线程饥饿”在这里比“死锁”更合适).

您看到死锁的原因很简单:您在
ch1
上运行,但从未关闭它,因此for循环从未终止

您可以通过手动在每个树上迭代一定次数来修复此问题,就像
main()
中的0..10循环一样:

//这一点决定了树
//t1和t2包含相同的值。
func-Same(t1,t2*tree.tree)bool{
ch1:=制造(成交量)
ch2:=制造(成交量)
步行(t1,ch1)
步行(t2,ch2)
对于i:=0;i<10;i++{

c:=您看到死锁的原因很简单:您在
ch1
上运行,但从未关闭它,因此for循环从未终止

您可以通过手动在每个树上迭代一定次数来修复此问题,就像
main()
中的0..10循环一样:

//这一点决定了树
//t1和t2包含相同的值。
func-Same(t1,t2*tree.tree)bool{
ch1:=制造(成交量)
ch2:=制造(成交量)
步行(t1,ch1)
步行(t2,ch2)
对于i:=0;i<10;i++{

c:=小心,结果可能会因树结构的不同而不同!原始代码检查树的中缀遍历是否相同,而此代码检查后缀遍历。两者的限制性都比检查树是否实际相同要小。错误原因是没有将值发送到在另一端接收。如果条件应该满足,那么我们还必须向通道发送一个值。在右节点漫游后发送当前节点的值违反了二叉树的有序语义。并且他的原始代码肯定是在右节点上调用walk。a)功能不应更改B)避免死锁的唯一原因是后缀遍历不同,而中缀相同。调用相同的(x,x)仍然会导致死锁,当通道耗尽时,仍然会发生同样的情况,返回true。是的,我会仔细研究,结果可能会因树结构而异!原始代码检查树的中缀遍历是否相同,而此代码检查后缀遍历。这两个与检查树是否实际相同相比,它们的限制性更小。错误的原因是没有向另一端接收的通道发送值。如果满足条件,则我们还必须向通道发送值。在正确的节点行走后发送当前节点的值违反了二叉树的有序语义。他的原始代码肯定是在右边的节点上调用Walk。A)功能不应该更改B)死锁是因为后缀遍历不同而避免的,而中缀是相同的。调用相同的(x,x)仍然会导致死锁,当通道耗尽时,仍然会发生在打算返回true时。是的,我会研究它
func WalkTreeAndThenCloseChannel(t *tree.Tree, ch chan int) {
    Walk(t, ch)
    close(ch)
}

func Same(t1, t2 *tree.Tree) bool {
    ch1 := make(chan int)
    ch2 := make(chan int)
    go WalkTreeAndThenCloseChannel(t1, ch1);
    go WalkTreeAndThenCloseChannel(t2, ch2);
// 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 := 0; i < 10; i++ {
        c := <-ch1
        d := <-ch2
        if c-d != 0 {
            return false
        }

    }
    return true
}
// Walk walks the tree t sending all values
// from the tree to the channel ch.
func Walk(t *tree.Tree, ch chan int, wg *sync.WaitGroup) {
    defer wg.Done()
    if t.Left != nil {
        wg.Add(1)
        Walk(t.Left, ch, wg)
    }
    ch <- t.Value
    if t.Right != nil {
        wg.Add(1)
        Walk(t.Right, ch, wg)
    }

}

// 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)

    var wg1 sync.WaitGroup
    wg1.Add(1)
    go Walk(t1, ch1, &wg1)
    go func() {
        wg1.Wait()
        close(ch1)
    }()

    var wg2 sync.WaitGroup
    wg2.Add(1)
    go Walk(t2, ch2, &wg2)
    go func() {
        // not strictly necessary, since we're not ranging over ch2, but here for completeness
        wg2.Wait()
        close(ch2)
    }()

    for c := range ch1 {
        d := <-ch2
        if c-d != 0 {
            return false
        }

    }
    return true
}