fmt.Println 问题与线程打印顺序不一致

Issue with fmt.Println not consistent with thread printing order

考虑以下代码

package main

import (  
    "fmt"
    "runtime"
    "sync"
)

func main() {
    messages := make(chan bool)
    var wg sync.WaitGroup
    var x = 1000

    wg.Add(runtime.NumCPU())
    for i := 0; i < runtime.NumCPU(); i++ {
        go func(x int) {
            defer wg.Done()
            var i = 0
            for i < x {
                i += 1
                fmt.Println(i * i)
            }
            messages <- true
        }(x)
    }

    go func() {
        for i := range messages {
            fmt.Println(i)
        }
    }()

    wg.Wait()
}

以及下面最后几行输出

980100
982081
984064
true
988036
990025
992016
994009
996004
998001
1000000

因为 message <- true 总是在 for 循环的末尾并且

    for i := range messages {
        fmt.Println(i)
    }

频道收到消息后打印。

我希望 true

一样总是打印在最后
988036
990025
992016
994009
996004
998001
1000000
true

但我发现这只是有时是正确的,为什么呢?

您正在做的是:

  1. 启动多个 goroutine,数量等于系统上的 CPU 数量。
  2. 启动一个额外的 goroutine,它从 messages 通道读取并打印值。
  3. 等待来自#1 的 goroutines 终止
  4. 退出

因为您只是在等待第一批 goroutine 终止,所以不能保证在程序终止之前打印所有(甚至任何)messages 值。