gpt4 book ai didi

go - Go 运行时如何检查 goroutine 是否被阻塞?

转载 作者:IT王子 更新时间:2023-10-29 01:04:40 26 4
gpt4 key购买 nike

Go 文档说:

When a coroutine blocks, such as by calling a blocking system call, the run-time automatically moves other coroutines on the same operating system thread to a different, runnable thread so they won't be blocked

但是运行时如何检测到 goroutine 被阻塞了?

例如,如果我将在一个 go-routine 中运行计算,它会被评估为阻塞操作吗?

package main

import (
"fmt"
"runtime"
)

func f(from string, score int) {
for i := 0; i < score; i++ {
for z := 0; z < score; z++ {
}
}

fmt.Println(from, " Done")
}

func main() {
runtime.GOMAXPROCS(1)
f("direct", 300000)
go f("foo", 200000)
go f("bar", 20000)
go f("baz", 2000)

go func(msg string) {
fmt.Println(msg)
}("going without loop")

var input string
fmt.Scanln(&input)
fmt.Println("done")
}

我得到的结果是:baz, boo bar。但为什么? Go 是否理解 foo 是阻塞的?

最佳答案

这张工单与问题相关:

https://github.com/golang/go/issues/11462

您可以执行的每个阻塞调用都将由运行时提供服务。所以运行时知道是否发生了可能阻塞的事情。

例如:

  1. 如果您在 sync.Mutex 上调用 Lock(),运行时将处理它并检查是否会阻塞并采取相应行动。

  2. 如果您在 exec.Cmd 上调用 Run()Output()(或类似方法),运行时会通知并假设此调用将阻塞。它不知道你正在运行的程序是否会阻塞,所以它必须假设最坏的情况。

据我所知,有两种主要机制,goroutine 如何阻塞,上面的示例是每种机制的示例。

  1. 是运行时在没有“外部”帮助的情况下为您提供的事物的示例。

  2. 是涉及系统调用的示例。例如,Linux 上的 Golang 不使用 gnu libc,而是通过调用 os.所有这些调用都通过包 syscall 进行(据我所知),这里运行时只有一个钩子(Hook)来通知发生的事情。

当然,这幅图可能有点模糊,golang 需要来自操作系统的互斥体以实现跨操作系统线程同步,即使对于 1。然后它在某种程度上也有点像示例 2。

关于问题中的代码:不。如果编译器没有优化循环,Go 不明白 f 可能会花费很多时间。在如此紧密的循环中,go 调度程序无法“停止”goroutine 并将另一个 goroutine 设置为运行,因为循环中没有抢占点。所以如果你有多个这样的 goroutines 做紧密的循环如果没有抢占点,它们可能会耗尽您的 CPU,所有其他 goroutine 都必须等待,直到至少完成一个紧密循环。但只有在该循环中调用不同的函数才能改变画面,作为一个函数调用是一个抢占点。

user1432751 在评论中提问:

what happens with CPU registers when blocking operation is happen? Current thread is blocking by goroutines, Go scheduler create new system thread and migrate all other threads there? –

go 调度不是抢占式的(至少那是我上次检查时的状态),而是在某些抢占点进行调度。例如系统调用、发送和等待 channel ,如果我没记错的话函数调用。因此,在这些点上,当调度程序决定要做什么时,调用内部函数并且与 goroutine 中执行的代码相关的 cpu 寄存器已经在堆栈中。

是的,如果系统调用已完成,因此存在操作系统线程阻塞的危险,执行系统调用的 goroutine 将获得自己的操作系统线程,这甚至不计入 GOMAXPROCS。

关于go - Go 运行时如何检查 goroutine 是否被阻塞?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46628053/

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