2016-10-02 115 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) 
    } 

}