【问题标题】:why main goroutine always be the second to be invoked为什么 main goroutine 总是第二个被调用
【发布时间】:2017-06-20 15:21:47
【问题描述】:
package main
import (
  "sync"
  "time"
  )
func main() {
  var wg sync.WaitGroup

  wg.Add(1)

  go func() {         //A
    wg.Wait()
    println("wait exit")
  }()

  go func() {
    time.Sleep(time.Second)
    wg.Done()
  }()

  wg.Wait()
  println("main exit")
}

结果:

wait exit
main exit

为什么main goroutine不先执行println("main exit"),而main thread dead然后丢弃一个goroutine? 它像结果显示的那样继续打印

【问题讨论】:

    标签: go concurrency goroutine


    【解决方案1】:

    机会。

    语言规范中没有规定您的“等待退出”应该在“主退出”之前或之后执行。

    如果您运行程序足够多次,有时“主出口”会首先运行。但也可能不是。结果未定义,取决于运行时状态和实现。因此,结果甚至可能在 Go 版本之间发生变化。

    【讨论】:

    • 我试过很多次了,如果这是机缘巧合,我想也许它应该至少出现一次。
    • @JunAn 尝试使用 -race 运行程序。当使用 -race 编译时,运行时会在某种程度上随机化 goroutine 的运行顺序。使用 -race 我大部分时间都会得到不同的输出。
    • @JunAn:订单未定义,这意味着当前运行时实现可能仍然会以一致的方式影响订单。如果您使用的是游乐场,那么您每次只是检索相同的缓存结果。只是不要依赖你不创建订单的订单。
    • 除了上面的答案和 cmets,将runtime.LockOSThread() 添加到 2 个打印 goroutine 并多次运行它,我运行时只打印了“主出口”(程序终止在其他文本可以打印之前)。
    • 为了记录,在单核系统上,goroutine 调度,在大多数情况下,是确定性的。有机会进入一个重新调度该 goroutine 的函数(以防止持续旋转的例程导致线程饱和),但除此之外,调度程序对于何时可能发生 goroutine 交换具有一致的规则(阻塞通道操作、网络调用、睡眠、和其他一些人)。这种行为没有得到很好的记录,也没有在规范中定义,因此可以在不通知且不破坏向后兼容性保证的情况下更改实现。
    猜你喜欢
    • 1970-01-01
    • 2023-03-12
    • 1970-01-01
    • 2020-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多