Go scheduler and CGO: Please explain this difference of behavior?

核能气质少年 提交于 2019-12-30 13:25:28

问题


I'd like to know the implementation reason for this:

package main

func main() {
    c := make(chan struct{})

    go func() {
        print("a")
        for {
        }
    }()

    go func() {
        print("b")
        for {
        }
    }()

    go func() {
        print("c")
        c <- struct{}{}
        for {
        }
    }()

    <-c
}

❯❯❯ GOMAXPROCS=2 go run sample1.go                                    
ab  <--- blocks.

package main

// static void loop() { for(;;); }
import "C"

func main() {
    c := make(chan struct{})

    go func() {
        print("a")
        C.loop()
        print("x")
    }()

    go func() {
        print("b")
        C.loop()
        print("y")
    }()

    go func() {
        print("c")
        c <- struct{}{}
        C.loop()
        print("z")
    }()

    <-c
}

❯❯❯ GOMAXPROCS=2 go run sample2.go                                    
abc  <--- ends gracefully.

More specifically I mean how the C tight loop differs from the Go one in the context of go routine scheduling. And even though the C tight loops should be being abruptly terminated at the end of the Go program, I'd like to know whether it's safe to rely on this behavior to start C tasks without blocking the Go program.


回答1:


The runtime can't preempt a true busy-loop. A CPU intensive loop with no scheduling points has to be in it's own thread for other goroutines to be able to run. Function calls and channel send or receive operations all yield. Network IO is scheduled asynchronously, and file IO gets its own thread.

Generally setting GOMAXPROCS > 1 is sufficient, but since you have 3 of these loops, and only 2 threads, the scheduler is still blocked. If you have a valid CPU intensive loop that is making it difficult to schedule goroutines, you can call runtime.GoSched() periodically to yield to the scheduler. In the real world, the only place where this generally maters is a programming error where you have an empty loop.

All cgo calls happen in their own threads outside of the go runtime, so those loops have no effect on the main loop, other than wasting CPU.



来源:https://stackoverflow.com/questions/28835758/go-scheduler-and-cgo-please-explain-this-difference-of-behavior

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!