gpt4 book ai didi

go - Go Playground 和我机器上的 Go 之间存在差异?

转载 作者:IT王子 更新时间:2023-10-29 01:42:13 27 4
gpt4 key购买 nike

为了解决我对 goroutines 的一些误解,我去了 Go playground 并运行了 this code :

package main

import (
"fmt"
)

func other(done chan bool) {
done <- true
go func() {
for {
fmt.Println("Here")
}
}()
}

func main() {
fmt.Println("Hello, playground")
done := make(chan bool)
go other(done)
<-done
fmt.Println("Finished.")
}

如我所料,Go playground 返回错误:Process too long

这似乎暗示在 other 中创建的 goroutine 会永远运行。

但是当我在自己的机器上运行相同的代码时,我几乎立即得到了这个输出:

Hello, playground.
Finished.

这似乎暗示 other 中的 goroutine 在主 goroutine 完成时退出。 这是真的吗?还是主 goroutine 完成,而另一个 goroutine 继续在后台运行?

最佳答案

编辑:Go Playground 上的默认 GOMAXPROCS 已更改,现在默认为 8。在“过去”的日子里,它默认为 1。要获得问题中描述的行为,请使用 runtime.GOMAXPROCS(1) 将其显式设置为 1。

对所见内容的解释:

移动 Playground ,GOMAXPROCS1 ( proof )。

这意味着一次执行一个 goroutine,如果该 goroutine 没有阻塞,则调度程序不会被迫切换到其他 goroutine。

您的代码(就像每个 Go 应用程序一样)以执行 main() 函数(主 goroutine)的 goroutine 开始。它启动另一个执行 other() 函数的 goroutine,然后它从 done channel 接收数据——这会阻塞。所以调度器必须切换到另一个 goroutine(执行 other() 函数)。

在您的 other() 函数中,当您在 done channel 上发送一个值时,这使得当前 (other())和可运行的 main goroutine。调度器选择继续运行other(),由于GOMAXPROCS=1main()没有继续运行。现在 other() 启动另一个执行无限循环的 goroutine。调度器选择执行这个 goroutine,它需要永远进入阻塞状态,所以 main() 不会继续。

然后 Go Playground 的沙箱超时作为一种赦免:

process took too long

请注意 Go Memory Model只保证某些事件发生在其他事件之前,你不能保证 2 个并发 goroutines 是如何执行的。这使得输出不确定。

您不得质疑任何不违反 Go 内存模型的执行顺序。如果您希望执行到代码中的某些点(执行某些语句),则需要显式同步(您需要同步您的 goroutines)。

另请注意,Go Playground 上的输出已缓存,因此如果您再次运行该应用程序,它不会再次运行,而是会立即显示缓存的输出。如果您更改代码中的任何内容(例如插入空格或注释)然后再次运行它,它将被编译并再次运行。您会通过增加的响应时间注意到它。不过,使用当前版本 ( Go 1.6),您每次都会看到相同的输出。

在本地运行(在您的机器上):

当你在本地运行它时,GOMAXPROCS 很可能会大于 1,因为它默认为可用的 CPU 内核数(自 Go 1.5 起)。所以如果你有一个 goroutine 执行无限循环并不重要,另一个 goroutine 将同时执行,这将是 main(),当 main()返回,你的程序终止;它不会等待其他非 main goroutines 完成(参见 Spec: Program execution )。

另请注意,即使您将 GOMAXPROCS 设置为 1,您的应用程序很可能会在“短”时间内退出,因为调度程序实现将切换到其他 goroutines 并且而不是永远执行无限循环(但是,如上所述,这是不确定的)。当它执行时,它将是 main() goroutine,因此当 main() 完成并返回时,您的应用程序将终止。

在 Go Playground 上玩你的应用:

如前所述,默认情况下 GOMAXPROCS 在 Go Playground 上是 1。但是允许将其设置为更高的值,例如:

runtime.GOMAXPROCS(2)

如果没有显式同步,执行仍然是不确定的,但是您会观察到不同的执行顺序和终止而不会遇到超时:

Hello, playground
Here
Here
Here
...
<Here is printed 996 times, then:>
Finished.

Go Playground 上尝试这个变体.

关于go - Go Playground 和我机器上的 Go 之间存在差异?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36705801/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com