2016-10-02 114 views
1

我试图理解这段代码,不知道为什么第二次执行是在第一次执行之前执行的。如果有人能真正帮助我解决这个问题真是太棒了!goroutines执行顺序

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 

回答

2

你有什么明确的同步两个够程的顺序。如果您运行足够多的时间,您将看到以不同顺序打印fmt.Println的呼叫。在执行goroutines时,因为它们是并发操作,所以在执行和/或完成时没有任何保证。您需要使用各种标准库包或通道本身来同步并发运行的goroutines的执行。

例如(通过利用信道的阻塞性质,你可以这样做):

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

又如(显著不太实用,但这里看看其他共同去同步功能),你可以介绍一个等待组和一个通道上的范围:

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

}