douxiong5972 2017-10-08 06:08
浏览 50
已采纳

Go运行时如何检查goroutine是否被阻止?

Go docs says that:

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

But how does runtime detect that goroutine is blocked?

For example if I will run calculation in one of go-routine will it be evaluated as blocking operation?

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")
}

I am getting result: baz, boo bar. But why? Does Go understand that foo is blocking?

  • 写回答

3条回答 默认 最新

  • doumei9589 2017-10-08 06:24
    关注

    This ticket is relevant to the questions:

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

    Each blocking call you could do, will be served by the runtime. So the runtime knows if something happens which could block.

    For example:

    1. If you call Lock() on a sync.Mutex the runtime will handle that and checks wether that would block or not and act accordingly.

    2. If you call Run() or Output() (or the like) on a exec.Cmd the runtime notices that and assumes, that this call will block. It can't know wether the program you are running will block, so it has to assume the worst.

    To the best of my knowledge, there are two principle mechanisms, how a goroutine could block and the examples above are examples for each one.

    1. Is an example for things the runtime provides to you without "external" help.

    2. Is an example for things were a syscall is involved. Golang on linux for example doesn't use gnu libc and implements the syscalls it needs directly by calling the os. All those calls are going through package syscall (to the best of my knowledge) and here the runtime has a single hook to get notified of what happens.

    Of course the picture is a bit muddy as it might be, that golang needs a mutex from the os for cross os thread synchronization even for 1. and then it is also somehow a bit of example 2.

    Regarding the code in the question: No. Go doesn't understand that f might take a lot of time, if the loops aren't optimised away by the compiler. And in such a tight loop, the go scheduler can't "stop" the goroutine and set another as running, as there is no preemption point in the loop. So if you have mulitple of such goroutines doing tight loops without preemption points, they might eat up your cpus and all other goroutines have to wait, until at least one of the tight loops is done. But only calling a different function in that loop changes that picture, as a function call is a preemption point.

    user1432751 asked in a comment:

    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? –

    The go schedule isn't preemptive (at least that was the state last time I checked) but schedules at certain preemption points. For example syscalls, sends and waits on channels and if I remember correctly function calls. So at those points an internal function is called and the cpu registers relevent to the code executing in the goroutine are already on the stack, when the scheduler decides what to do.

    And yes, if a syscall is done and therefore there is the danger of a blocked os thread, the goroutine doing the syscall gets its own os thread, that doesn't even count to GOMAXPROCS.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 如何实验stm32主通道和互补通道独立输出
  • ¥30 这是哪个作者做的宝宝起名网站
  • ¥60 版本过低apk如何修改可以兼容新的安卓系统
  • ¥25 由IPR导致的DRIVER_POWER_STATE_FAILURE蓝屏
  • ¥50 有数据,怎么建立模型求影响全要素生产率的因素
  • ¥50 有数据,怎么用matlab求全要素生产率
  • ¥15 TI的insta-spin例程
  • ¥15 完成下列问题完成下列问题
  • ¥15 C#算法问题, 不知道怎么处理这个数据的转换
  • ¥15 YoloV5 第三方库的版本对照问题