goroutines执行顺序

时间:2016-10-02 14:56:28

标签: go goroutine

我试图理解这段代码,不知道为什么第二轮在第一条之前执行。如果有人能真正帮助我,那就太好了!

Private Sub StartServiceToolStrip_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles StartServiceToolStrip.Click
    Using login As New Login
        If (login.ShowDialog() = DialogResult.Cancel) Then
            Return
        End If
        ClientNotifyIcon.ShowBalloonTip(100, " Network", " Network service has been started...", ToolTipIcon.Info)
        StartServiceToolStrip.Enabled = False
        StopServiceToolStrip.Enabled = True
        receiveThread.Resume()
    End Using

End Sub

输出:

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

1 个答案:

答案 0 :(得分:6)

您没有明确同步两个goroutines的顺序。如果您运行足够多次,您将看到对fmt.Println的调用以不同的顺序打印。执行goroutine时,由于它们是并发操作,因此无法保证它们何时执行和/或完成。您需要使用各种标准库包或通道本身来同步并发运行的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)
    }

}