为什么这个关于golang goruntine运行顺序的代码首先是"2"

alp*_*yan 1 go goroutine

package main

import (
    "fmt"
    "sync"
)

func main() {
    runtime.GOMAXPROCS(1)
    w := &sync.WaitGroup{}
    w.Add(2)
    go func() {
        fmt.Println("1")
        w.Done()
    }()
    go func() {
        fmt.Println("2")
        w.Done()
    }()
    w.Wait()
}
Run Code Online (Sandbox Code Playgroud)

https://play.golang.org/p/ESi1mKAo1x_S

呃,我不知道为什么"2"首先打印.

我想检查一下这些信息.但是我不知道应该检查什么信息.所以我在那里发帖提问求助.

我认为第一个goroutine是第一个推入队列.它应该先打印.

icz*_*cza 6

您没有将两个启动的goroutine 彼此同步,因此无法保证它们的运行顺序.您同步的唯一事情是等待其他2完成的主要goroutine,但它们的顺序将是未定义的.

这是一个使用另一个同步订单的示例sync.WaitGroup:

w := &sync.WaitGroup{}
w.Add(2)

w2 := &sync.WaitGroup{}
w2.Add(1)
go func() {
    fmt.Println("1")
    w.Done()
    w2.Done()
}()
go func() {
    w2.Wait()
    fmt.Println("2")
    w.Done()
}()
w.Wait()
Run Code Online (Sandbox Code Playgroud)

输出将是(在Go Playground上尝试):

1
2
Run Code Online (Sandbox Code Playgroud)

基本上第二个goroutine等待w2,一旦完成就会在第一个goroutine中调用.

请注意,由于第二个goroutine等待第一个goroutine,因此主goroutine只等待第二个goroutine(这意味着等待两者)就足够了.所以上面的例子可以这样写:

w2 := &sync.WaitGroup{}
w2.Add(1)
go func() {
    fmt.Println("1")
    w2.Done()
}()

w := &sync.WaitGroup{}
w.Add(1)
go func() {
    w2.Wait()
    fmt.Println("2")
    w.Done()
}()
w.Wait()
Run Code Online (Sandbox Code Playgroud)

输出是一样的.在Go Playground尝试这个.