douye7033 2016-10-02 14:56
浏览 9
已采纳

goroutines执行顺序

I'm trying to understand this piece of code, not sure why the 2nd go is executed before the 1st one. It'd be great if someone can really help me out with this!

func sum(a []int, c chan int) {
   fmt.Println("summing: ", a)
   total := 0
   for _, v := range a {
      total += v
   }
   //fmt.Println("send to c",total)
   c <- total  // send total to c
}
func main() {
    //a := []int{7, 2, 8,134,23,23,1,23,1234,143, -9, 4, 0, 1234}

    c := make(chan int)

    go sum([]int{1,2,3}, c)
    go sum([]int{4,5,6}, c)

    x := <-c
    fmt.Println(x)
    x = <-c
    fmt.Println(x)
}

OUTPUT:

summing:  [4 5 6]
15
summing:  [1 2 3]
6
  • 写回答

1条回答 默认 最新

  • dongsu2807 2016-10-02 15:05
    关注

    You have nothing explicitly synchronizing the order of the two goroutines. If you run this enough times, you will see the calls to fmt.Println print in different sequences. When executing goroutines, as they are concurrent operations, you have no guarantees when they will execute and/or complete. You need to use various standard library packages, or channels themselves to synchronize the execution of concurrently running goroutines.

    For example (by leveraging the blocking nature of channels, you could do something like):

    func main() {
    
        c := make(chan int)
    
        go sum([]int{1, 2, 3}, c)
    
        //use the channel to block until it receives a send
        x := <-c
        fmt.Println(x)
    
        //then execute the next routine
        go sum([]int{4, 5, 6}, c)
    
        x = <-c
        fmt.Println(x)
    }
    

    Another example (significantly less practical, but here to look at other common go synchronization features) you could introduce a wait group, and a range over a channel:

    func sum(a []int, c chan int, wg *sync.WaitGroup) {
        defer wg.Done()
        fmt.Println("summing: ", a)
        total := 0
        for _, v := range a {
            total += v
        }
        //fmt.Println("send to c",total)
        c <- total // send total to c
    }
    
    func main() {
    
        c := make(chan int)
        wg := new(sync.WaitGroup)
    
        //concurrently call the concurrent calls to sum, allowing execution to continue to the range of the channel 
        go func() {
            //increment the wait group, and pass it to the sum func to decrement it when it is complete
            wg.Add(1)
            go sum([]int{1, 2, 3}, c, wg)
            //wait for the above call to sum to complete
            wg.Wait()
            //and repeat...
            wg.Add(1)
            go sum([]int{4, 5, 6}, c, wg)
            wg.Wait()
            //all calls are complete, close the channel to allow the program to exit cleanly 
            close(c)
        }()
    
        //range of the channel
        for theSum := range c {
            x := theSum
            fmt.Println(x)
        }
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 找一个网络防御专家,外包的
  • ¥100 能不能让两张不同的图片md5值一样,(有尝)
  • ¥15 informer代码训练自己的数据集,改参数怎么改
  • ¥15 请看一下,学校实验要求,我需要具体代码
  • ¥50 pc微信3.6.0.18不能登陆 有偿解决问题
  • ¥20 MATLAB绘制两隐函数曲面的交线
  • ¥15 求TYPCE母转母转接头24PIN线路板图
  • ¥100 国外网络搭建,有偿交流
  • ¥15 高价求中通快递查询接口
  • ¥15 解决一个加好友限制问题 或者有好的方案