发布时间:2023-01-12 22:00
虽然Go 编译器产生的是本地可执行代码,但是这些代码仍旧运行在 Go 的 runtime(这部分的代码可以在 runtime 包中找到)当中。Go的运行时,可以通过runtime包中的函数,设置go运行时的环境,比如运行最大有多少逻辑处理器§,最多可以创建多少OS线程(M)等。
函数名 | 用途 |
---|---|
Gosched | 让当前协程(goroutine)退出,让其他协程运行 |
Goexit | 退出当前goroutine(但是defer语句回照常执行) |
GOMAXPROCS <1> | 设置最大的可使用的CPU核数 |
NumCPU | 返回当前系统的CPU核数量 |
NumGoroutine | 返回正在执行和排队的任务总数 |
GOOS | 目标操作系统 |
GOROOT | 返回本机GO路径 |
GC <2> | 让运行时系统进行一次强制性的垃圾收集 |
补充
<1> : 在 go 1.5之前,GOMAXPROCS默认是1,1.5之后默认是CPU核数
<2> : 垃圾回收分为强制的垃圾回收(不管怎样,都要进行的垃圾回收。)和非强制的垃圾回收(只会在一定条件下进行的垃圾回收(即运行时,系统自上次垃圾回收之后新申请的堆内存的单元(也成为单元增量)达到指定的数值))
package main
import (
"fmt"
"runtime"
"sync"
)
var wg sync.WaitGroup
func main() {
fmt.Println(runtime.NumCPU()) // 该系统的逻辑核数: 8
fmt.Println(runtime.GOROOT()) // 本机GO路径: D:\Program Files\Go
runtime.GOMAXPROCS(1) // 设置为1,方便下方演示
for i := 0; i < 4; i++ {
wg.Add(2)
go test()
go test1()
}
fmt.Println(runtime.NumGoroutine()) // 9,有9个goroutine在执行或者等待
wg.Wait()
fmt.Println(runtime.GOOS) // 目标操作系统: windows
}
func test() {
fmt.Println("test开始")
runtime.Gosched() // 调度其他goroutine先执行
fmt.Println("test结束")
wg.Done()
}
func test1() {
defer func() {
fmt.Println("defer正常执行")
}()
fmt.Println("test1开始")
wg.Done() // 写在 Goexit 下方就不执行了
runtime.Goexit() // 退出当前goroutine,下方代码不会执行,但是不影响之前定义的defer
fmt.Println("test1结束")
}
可以看出,在 GOMAXPROCS 设置为1 时,不使用 Gosched 打印出来的结果 test开始 和 结束时连在一起的,使用之后,执行到Gosched时就会 调度其他的线程来执行。因此 开始和结束之间有其他的打印结果。并且 test1结束 永远不会打印出来。