2016-10-02 2 views
1

Я пытаюсь понять этот кусок кода, не знаю, почему 2-й ход выполняется до 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) 
} 

ВЫВОД:

summing: [4 5 6] 
15 
summing: [1 2 3] 
6 

ответ

2

У Вас нет ничего явно синхронизатора порядок двух goroutines. Если вы запустили это достаточно, вы увидите вызовы на печать 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) 
    } 

} 
Смежные вопросы