1.Goroutine是Go语言的协程(Coroutine),Groutine从语言层面上实现了并发,和线程一样共享堆,不共享栈,但是避免了切换上下文的额外开销。
2.Go语言使用CSP(Communicating sequential processes)并发模型,讲究“以通信的方式共享内存”,而不是“以共享内存的方式通信”
3.Go线程实现模型MPG:
- M指Machine,一个M关联一个内核线程,由操作系统管理
- P指Processor,代表M所需的上下文环境,也是处理用户级代码逻辑的处理器,负责衔接M和G的调度上下文将等待执行的M和G对接
- G指Goroutine,本质上是轻量级线程,包括了调用栈,重要的调度信息,例如channel
P的数量由环境变量GOMAXPROCS决定,通常和核心数对应,G会有很多个,每个P将Goroutine从一个就绪队列中做Pop操作,减小锁竞争,通常每个P负责一个队列
上图中正在执行的G是蓝色,待执行状态的G是灰色,灰色G形成一个队列runqueues,Go语言中启动一个goroutine就用一次go function,每有一个go语句被执行,runqueues就在末尾加入一个G,一旦上下文运行G直到调度点,它会从其runqueue中弹出G并开始运行
Q:可以抛弃上下文P直接将G挂在M上吗?
A:不可以,需要上下文的目的是让当遇到内核线程阻塞的时候,我们可以将P直接挂到其他线程M,上下文P会定期检查全局goroutine队列中的G,以便自身队列空时有事可做,假如全局gouroutine队列夜空了,它还可以从别的P的runqueue里偷,Go的做法是直接从其他P中偷一半的G,所以P最重要的作用就是均衡地分配工作
- Goroutine小结
- 优点:开销小, 调度性能好
- 缺点:调度机制无法实现公平调度