Goroutine sleep and deadlock in code. How to solve it?

后端 未结 2 1942
借酒劲吻你
借酒劲吻你 2021-01-16 10:39

http://play.golang.org/p/r92-KtQEGl

I am trying to execute this code. It throws a deadlock error.

What am I missing?

package main

import \"t         


        
相关标签:
2条回答
  • 2021-01-16 11:15

    You need at least to initialize your channels (if the channel is nil, a range would block forever)

      var temp chan int = make(chan int)
      var ch chan int = make(chan int)
    

    See http://play.golang.org/p/Gh8MZlyd3B (still deadlock but at least display results)

    This version, using two temp channels, doesn't deadlock: http://play.golang.org/p/KsnmKTgZ83

    package main
    
    import "tour/tree"
    import "fmt"
    
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func Walk(t *tree.Tree, ch chan int) {
        var temp1 chan int = make(chan int)
        var temp2 chan int = make(chan int)
        ch <- t.Value
        if t.Left != nil {
            go Walk(t.Left, temp1)
        }
        if t.Right != nil {
            go Walk(t.Right, temp2)
        }
        if t.Left != nil {
            for i := range temp1 {
                ch <- i
            }
        }
        if t.Right != nil {
            for i := range temp2 {
                ch <- i
            }
        }
        close(ch)
    }
    
    // Same determines whether the trees
    // t1 and t2 contain the same values.
    func Same(t1, t2 *tree.Tree) bool
    
    func main() {
        var ch chan int = make(chan int)
        go Walk(tree.New(1), ch)
        for i := range ch {
            fmt.Println(i)
        }
    }
    
    0 讨论(0)
  • 2021-01-16 11:29

    So I did this by by sending in a flag into the Walk function. This way it knows when it can close down the channel. I also think it's important to walk the tree in the right order Left node, Value, Right node.

    package main
    
    import (
      "fmt"
      "tour/tree"
    )
    
    // Walk walks the tree t sending all values
    // from the tree to the channel ch.
    func Walk(t *tree.Tree, c chan int, d bool) {
      if t.Left != nil {
        Walk(t.Left, c, false)
      } 
      c <- t.Value
    
      if t.Right != nil {
        Walk(t.Right, c, false)
      }
      if d {
        close(c)
      }
    }
    
    // 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, true)
      go Walk(t2, ch2, true)
      for {
        v1, ok1 := <-ch1
        v2, ok2 := <-ch2
    
        if v1 != v2 {
          return false
        }
        if ok1 != ok2 {
          return false
        } 
        if !ok1 && !ok2 {
          return true
        }
      }
      return false
    }
    func main() {
      ch := make(chan int)
      go Walk(tree.New(1), ch, true)
    
      for i := range ch {
        fmt.Println(i)
      } 
    
      test1 := Same(tree.New(1), tree.New(1))
      test2 := Same(tree.New(1), tree.New(2))
    
      fmt.Println(test1, test2)
    }
    
    0 讨论(0)
提交回复
热议问题