Golang Scheduler
调度器由三方面实体构成:
- M:物理线程,类似于 POSIX 的标准线程;
- G:goroutine,它拥有自己的栈、指令指针和维护其他调度相关的信息;
- P:代表调度上下文,可将其视为一个局部调度器,使Golang代码跑在一个线程上
三者对应关系:
上图有2个 物理线程 M,每一个 M 都拥有一个上下文(P),每一个也都有一个正在运行的goroutine(G)。
runtime.GOMAXPROCS()
调度器为什么要维护多个上下文P 呢?因为当一个物理线程 M 被阻塞时,P 可以转而投奔另一个OS线程 M(即 P 带着 G 连茎拔起,去另一个 M 节点下运行)。这是 Golang调度器厉害的地方,也是高并发能力的保障。
package main
import (
"fmt"
)
/*
CSP 描述这样一种并发模型:多个Process 使用一个 Channel 进行通信, 这个 Channel 连结的 Process 通常是匿名的,消息传递通常是同步的
*/
/*
无缓冲的chan,在一个goroutine读写会导致死锁
*/
func unbuffer_chan() {
ch := make(chan int)
ch <- 100
fmt.Printf("recieve data :%d\n", <-ch)
}
/*
有缓冲的chan,在一个goroutine中读写不会导致死锁
*/
func buffer_chan() {
ch := make(chan int, 1)
ch <- 100
fmt.Println(<-ch)
}
/*
main 就是一个goroutine
*/
func main() {
buffer_chan()
}