在Go程序中,有三个后台goroutine。

huangapple go评论79阅读模式
英文:

What are the three background goroutines in a Go program?

问题

Go似乎始终至少有4个goroutine在任何给定时间运行。其他三个不是主goroutine的是什么?

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Println(runtime.NumGoroutine()) //4
}

在这段代码中,除了主goroutine之外,还有三个其他的goroutine。

英文:

Go seems to always have at least 4 goroutines running at any given time. What are the other three that are not the main goroutine?

http://play.golang.org/p/MQBiLmHXBK

package main

import (
	"fmt"
	"runtime"
)

func main() {
	fmt.Println(runtime.NumGoroutine()) //4
}

答案1

得分: 8

那些不是线程,而是 goroutine,其数量可能根据当前实现而变化(例如,在 go1.2 中,它将打印 2)。

现在,看起来你有一个 main 的 goroutine,以及三个 runtime/gc 的 goroutine。

import "fmt"

func main() {
    fmt.Println(func() string { panic(nil); return "" }())
}

这显示了以下内容:

goroutine 16 [running]:
runtime.panic(0x0, 0x0)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
main.func·001(0x3ea4f, 0xdc4b0)
    /test/threads.go:6 +0x28
main.main()
    /test/threads.go:6 +0x1e

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
    /usr/local/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 18 [runnable]:
bgsweep()
    /usr/local/go/src/pkg/runtime/mgc0.c:1976
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 19 [runnable]:
runfinq()
    /usr/local/go/src/pkg/runtime/mgc0.c:2606
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445

如果你移除 fmt,并使用引导的 print 函数,你只会得到两个 goroutine。

import "runtime"

func main() {
    print(runtime.NumGoroutine(), "\n")
}

// 输出 2

如果你想要知道正在运行的 goroutine,可以打印堆栈跟踪、调用 panic,或者使用 SIGQUIT 终止进程(它会打印堆栈跟踪并退出)。如果你运行最小的程序,你可以得到两个 goroutine 的堆栈跟踪:

package main

func main() {
    panic(nil)
}

Goroutine 的开销非常低,许多事情会启动和停止更多的 goroutine,因此追踪它们的下限并没有太大用处。请注意,即使只有两个 goroutine(main/runtime.panic 和 runtime.MHeap_Scavenger),计数已经达到了 17。

panic: nil

goroutine 16 [running]:
runtime.panic(0x0, 0x0)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
main.main()
    /test/threads.go:4 +0x28

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
    /usr/local/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445
exit status 2
英文:

Those aren't threads, they're goroutines, and the number may vary based on current implementation (i.e. in go1.2 it would have printed 2).

Right now, it looks like you have 1 for main, and 3 for runtime/gc.

import "fmt"

func main() {
	fmt.Println(func() string { panic(nil); return "" }())
}

This shows

goroutine 16 [running]:
runtime.panic(0x0, 0x0)
	/usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
main.func·001(0x3ea4f, 0xdc4b0)
	/test/threads.go:6 +0x28
main.main()
	/test/threads.go:6 +0x1e

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
	/usr/local/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 18 [runnable]:
bgsweep()
	/usr/local/go/src/pkg/runtime/mgc0.c:1976
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445

goroutine 19 [runnable]:
runfinq()
	/usr/local/go/src/pkg/runtime/mgc0.c:2606
runtime.goexit()
	/usr/local/go/src/pkg/runtime/proc.c:1445

if you remove fmt, and use the bootstrapping print function you only get 2 goroutines.

import "runtime"

func main() {
	print(runtime.NumGoroutine(), "\n")
}

// prints 2

If you ever want to know exactly what goroutines are running, print a stack trace, call panic, or kill the process with SIGQUIT (which prints a stack trace and exits). If you run the absolute minimum program you can get a stack trace from you can see the 2 goroutines:

package main

func main() {
	panic(nil)
}

Goroutines are very inexpensive, and many things will start and stop more goroutines, so trying to track their lower bound isn't very useful. Notice how even though there's only 2 goroutines, (main/runtime.panic, and runtime.MHeap_Scavenger), the count is already up to 17.

panic: nil

goroutine 16 [running]:
runtime.panic(0x0, 0x0)
    /usr/local/go/src/pkg/runtime/panic.c:279 +0xf5
main.main()
    /test/threads.go:4 +0x28

goroutine 17 [runnable]:
runtime.MHeap_Scavenger()
    /usr/local/go/src/pkg/runtime/mheap.c:507
runtime.goexit()
    /usr/local/go/src/pkg/runtime/proc.c:1445
exit status 2

huangapple
  • 本文由 发表于 2014年9月9日 23:04:53
  • 转载请务必保留本文链接:https://go.coder-hub.com/25747970.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定