理解GPM
Go语言的scheduler的实现原理
Go语言中支撑整个scheduler实现的主要有四个结构,分别是G、P、M、Sched,前三个定义在runrtime.h,Sched定义在proc.c中。
- Sched结构就是调度器,维护了存储M和G的队列,以及调度器的一切状态信息
- G是goroutine实现的核心结构,是对一个要并发执行的任务的封装,可以称作为用户态的线程,属于用户级资源,对操作系统透明,轻量级,可以大量创建,上下文的切换成本低。
- P是Processor,逻辑处理器,主要作用是管理G对象,并为G在M上的运行提供本地化资源,他维护了一个goroutine队列runqueue,也可以理解为goroutine的上下文环境。
- M是Machine,是利用系统调用创建出来的操作系统线程实体,作用是执行G中的并发任务,代表了一个内核线程,由操作系统管理,goroutine就是运行在M上的,M中维护了小对象内存mcache,当前执行的goroutine,随机数发生器等信息。
runtime包
runtime类似于Java或者.Net中的虚拟机,负责内存分配,垃圾回收,goroutine,chanel,切片,map,反射等等。
runtime包的常用函数
package main
import (
"fmt"
"runtime"
)
func main() {
//获取goroot目录
fmt.Println("GOROOT: ", runtime.GOROOT())
//获取操作系统
fmt.Println("os/platform: ", runtime.GOOS)
//获取当前逻辑cpu的数量,当然也可以用runtime.GOMAXPROCS()手动设置逻辑CPU的数量,不过GO1.8之后不用设置,默认运行在多核
fmt.Println("逻辑cpu的数量: ", runtime.NumCPU())
//GOsched: 让当前的额goroutine让出当前的时间片,当一个goroutine发生阻塞的时候,go会把所有和这个阻塞goroutine处于
//同一个系统线程中的其他goroutine移植到其他系统线程上从而使之不被阻塞。
go func() {
for i := 0; i < 3; i++ {
fmt.Println("goproutine")
}
}()
for i := 0; i < 3; i++ {
//让出时间片,让其他goroutine先执行
runtime.Gosched()
fmt.Println("...........................main")
}
}
package main
import (
"fmt"
"runtime"
"time"
)
func main() {
go func() {
fmt.Println("goroutine开始")
//调用fun
fun()
fmt.Println("goroutine结束")
}()
//为了主程序不结束 我们让他睡一会
time.Sleep(3 * time.Second)
}
func fun() {
defer fmt.Println("defer job")
runtime.Goexit() //终止当前的goroutine
fmt.Println("fun函数")
}
其他还有很多,用到的时候可以查看官方文档:https://golang.google.cn/pkg/
参考资料:bilibili
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。