随着服务器硬件的升级,配置越来越高,为了充分利用服务器资源,并发变成也就变得越来越重要。
并发:逻辑上具有处理多个同时任务的能力。
并行:物理上同一时刻执行多个并发任务。
通常所说的并发编程,也就是说它允许多个任务同时执行,但实际上并不一定在同一时刻被执行。在单核处理器上,通过多线程共享CPU时间片串行执行。
多线程和多进程是并行的基本条件。但是单线程也可以用协程来实现并发。
1,G
G就是Goroutine的缩写。相当于操作系统中的进程控制块。这里就是goroutine的控制结构。是对goroutine的抽象。其中包含执行的函数指令和参数。G保存的任务对象。上下文切换,现场保护和现场保护恢复需要的寄存器(SP,IP)等信息
2,M
M是一个线程,所有的M是有线程栈的。如果不对该线程栈分配内存,那么系统将会为线程栈分配内存。当指定了线程栈,M的PC寄存器指向G提供的函数,然后去执行。
3,P
Processor是一个抽象的概念。并不是真正的物理CPU。所以当P有任务时需要创建和唤醒一个系统线程来执行它队列的任务。所以P/M需要进行绑定,构成一个执行单元。
P决定了同事可以并发任务的数量,可通过GOMAXPROCS限制同时执行用户级任务的操作系统线程。可以通过runtime.GOMAXPROCS进行制定。
GO的调度器调度过程
首先创建一个G对象,G对象保存到P的本地队列或者全局队列。P此时去唤醒一个M,P继续执行它的执行序。M寻找是否有空闲的P,如果有则将该G对象移动到它本身。接下来M执行一个调度循环(调用G对象->执行->清理线程->继续找新的Goroutine执行)
M执行过程中,随时会发生上下文切换。当发生上下文切换时,需要对执行现场进行保护,以便下次被调度执行时进行现场恢复。Go调度器M的栈保存在G对象上,只需要将M所需要的寄存器(SP,PC等)保存到G 对象上就可以实现现场保护。当这些寄存器数据被保护起来,就随时做上下文切换了,在中断之前把现场保存起来。如果此时G任务还没有执行完。M可以将任务重新丢到P的任务队列,等待下一次被调度执行。当再次被调度执行时,M通过访问G的vdsoSP,vdsoPC寄存器进行现场恢复。