Go 调度程序和 CGO:请解释这种行为差异?
Go scheduler and CGO: Please explain this difference of behavior?
想知道实现原因:
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.
更具体地说,我指的是在 go 例程调度的上下文中,C 紧密循环与 Go 紧密循环有何不同。即使 C 紧密循环应该在 Go 程序结束时突然终止,我想知道依靠这种行为来启动 C 任务而不阻塞 Go 程序是否安全。
运行时间无法抢占真正的忙循环。一个没有调度点的 CPU 密集循环必须在它自己的线程中,其他 goroutine 才能 运行。函数调用和通道发送或接收操作都会产生。网络IO是异步调度的,文件IO有自己的线程。
通常设置 GOMAXPROCS
> 1 就足够了,但是由于您有 3 个这样的循环,并且只有 2 个线程,调度程序仍然被阻塞。如果您有一个有效的 CPU 密集循环,这使得调度 goroutine 变得困难,您可以定期调用 runtime.GoSched()
以屈服于调度程序。在现实世界中,这通常唯一重要的地方是出现空循环的编程错误。
所有 cgo 调用都发生在 go 运行time 之外的它们自己的线程中,因此这些循环对主循环没有影响,除了浪费 CPU。
想知道实现原因:
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.
更具体地说,我指的是在 go 例程调度的上下文中,C 紧密循环与 Go 紧密循环有何不同。即使 C 紧密循环应该在 Go 程序结束时突然终止,我想知道依靠这种行为来启动 C 任务而不阻塞 Go 程序是否安全。
运行时间无法抢占真正的忙循环。一个没有调度点的 CPU 密集循环必须在它自己的线程中,其他 goroutine 才能 运行。函数调用和通道发送或接收操作都会产生。网络IO是异步调度的,文件IO有自己的线程。
通常设置 GOMAXPROCS
> 1 就足够了,但是由于您有 3 个这样的循环,并且只有 2 个线程,调度程序仍然被阻塞。如果您有一个有效的 CPU 密集循环,这使得调度 goroutine 变得困难,您可以定期调用 runtime.GoSched()
以屈服于调度程序。在现实世界中,这通常唯一重要的地方是出现空循环的编程错误。
所有 cgo 调用都发生在 go 运行time 之外的它们自己的线程中,因此这些循环对主循环没有影响,除了浪费 CPU。