goroutines 的执行顺序

标签 go goroutine

我试图理解这段代码,不确定为什么第二次执行在第一次执行之前。如果有人真的能帮我解决这个问题,那就太好了!

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

最佳答案

您没有明确同步两个 goroutine 的顺序。如果您运行此程序足够多次,您将看到以不同的顺序打印对 fmt.Println 的调用。当执行 goroutines 时,因为它们是并发操作,您无法保证它们何时执行和/或完成。您需要使用各种标准库包或 channel 本身来同步并发运行的 goroutines 的执行。

例如(通过利用 channel 的阻塞特性,您可以做类似的事情):

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

另一个例子(不太实用,但这里是为了看看其他常见的 go 同步特性)你可以引入一个 WaitGroup ,以及一个 channel 上的范围:

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

}

关于goroutines 的执行顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39818254/

相关文章:

ubuntu - 如何在 Ubuntu 16.04 LTS 的 golang 中正确使用多个工作空间?

go - 定义自定义HTML字符串化的最简单方法是什么?

戈兰 |如何检查单个 if 语句中的多个 bool 值是否为 true?

go - 在golang中优先处理goroutine

windows - 可以不 Hook 所有可用的 CPU 电源吗?

multithreading - 我怎样才能拥有一个等待来自多个其他人的值的 goroutine 函数?

go - 如何“强制” Golang函数使用结构的新实例

dataframe - dataframe-go:如何使用<>运算符进行过滤?

goroutine 泄漏上下文超时?

go - 没有收到来自 channel 的消息