go - 关于goroutine无限循环和内存分配的问题

标签 go memory goroutine

所以我有一个程序需要分配一大块内存并永远保存它。作为测试,我还运行了一个运行无限循环的 goroutine,在我的主线程中,我分配了内存,但是即使我将 GOMAXPROCS 设置为大于 1,程序也会永远卡在 goroutine 的无限循环中。

func main() {
    runtime.GOMAXPROCS(2)
    go func() {
        for {
            //fmt.Printf("goroutine1\n")
        }
    }()
    fmt.Println("main thread1")
    x := [1145][1145]int{}
    for i := 0; i < 1144; i++ {
        fmt.Println(i)
        x[i][i] = i
    }
    fmt.Println("main thread2")

}

如果我在无限循环中不做任何事情,我的主线程 1 将永远无法成功分配内存并打印“主线程 2”,即使我将 GOMAXPROCS 设置为 2,如果我在无限循环中打印一些东西,一切正常(这是预期的,因为 goroutine 在无限循环中打印一些东西,它调用系统调用并产生 cpu,所以我的主线程可以分配内存。

我想知道为什么会这样?

最佳答案

你的底层计算机系统有一些线程执行器。 Go 运行时自己找出有多少,并创建适当数量的运行时执行程序以使用所有系统。更改 GOMAXPROCS 会更改运行时尝试分配的执行程序数量,但对底层系统没有影响。在这种情况下,似乎底层系统本身只有一个执行者。

如果你的底层系统有两个或更多,那么 Go 已经创建了两个执行器,并且会在其中一个上运行无限循环 goroutine,而你的 main另一方面,goroutine 同时。但是由于您的系统只有一个,所以只有一个可以运行。无论 Go 运行时可能创建多少运行时级别的执行程序,只有一个可以绑定(bind)到硬件 CPU 以实际运行。

请注意,goroutine 是多对 N 映射的。例如,假设您拆分出 1000 个 goroutine,并拥有 10 个 CPU。运行时将分配 10 个执行器并使用 10 个 CPU 一次运行 1000 个 goroutine 中的 10 个。剩下的 990 个 goroutine 等到其中一个执行者达到自愿停止运行该 goroutine 并选择剩余 990 个的点。

您可以调用 runtime.Gosched 你自己,从任何 goroutine 说:我自愿暂停自己,让其他想要运行的 goroutine 运行,直到执行者可以接我再次运行。许多其他系统调用此函数yield或一些变化。 (注意“暂停”这个词:我在这里使用它是为了生效,但是调用 runtime.Gosched 的 goroutine 在技术上并没有暂停,因为它仍然被标记为“想要运行”,而其他 goroutine 可能在技术上被暂停因为它们被标记为“现在不能运行,正在等待____”(填空)。)

另见 How do goroutines work? (or: goroutines and OS threads relation) .

关于go - 关于goroutine无限循环和内存分配的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58648083/

相关文章:

go - 如何用golang直接画到树莓派屏幕上

ssl - 使用 Golang 在 Nginx 后面运行的 GRPC 服务的 TLS

PHP读取和解析大文件?

c - 堆栈上的动态内存分配

go - 为什么调用 goroutines 的顺序和方式很重要?

go - 解决与 goroutines 的冲突?

go - 当所有 goroutines 完成时退出程序

go - 如何在Golang中正确使用OR运算符

go - 类型转换和类型断言有什么区别?

performance - 是否可以使用 ETW(Windows 事件跟踪)来收集内存统计信息?