2016-10-02 15 views
1

私はこのコードを理解しようとしていますが、第2回目が第1回より前に実行される理由はわかりません。誰かが本当にこれで私を助けてくれるなら、それは素晴らしいことでしょう!ゴルーチン実行順序

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

あなたが明示的に2つのゴルーチンの順序を同期は何もありません。これを十分に実行すると、fmt.Printlnへの呼び出しが異なる順序で表示されます。ゴルーチンを実行するとき、同時実行操作であるため、実行および/または完了の保証はありません。同時に実行するgoroutineの実行を同期するには、さまざまな標準ライブラリパッケージまたはチャネルを使用する必要があります。例えば

(チャンネルのブロッキングの性質を活用することで、あなたのような何かができる):

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

}