GMP
- G — 表示 Goroutine,它是一个待执行的任务;
- M — 表示操作系统的线程,它由操作系统的调度器调度和管理;
- P — 表示处理器,它可以被看做运行在线程上的本地调度器;
首先Go语言合理利用多核的进行并行处理,也就是多线程 对应GMP中的M。
为了减少内核级线程调用切换成本,Go基于协程进行程序任务执行单元。对应GMP中的G。
同时go实现对G的调度器,对应GMP中的P。
golang程序启动过程
runtime
runtime 也叫运行时,runtime包含了调度、内存管理、垃圾回收、内部数据结构、定时器和各种系统调用的封装等。可以说golang的强大都归功于runtime的实现。scheduler
scheduler 有调度器、日程安排的意识,这里是指调度器,它的工作是将准备好运行的goroutine分散到工作线程中执行。
程序启动,runtime.main 创建最初线程 m0 创建最初 goroutine g0 关联m0 和 g0 / 初始化调度器 创建 M P / 创建main的goroutine / 绑定M和P/ M使用P获取G/M设置G运行环境/M执行G/G退出
首先创建一个G对象,然后G被保存在P的本地队列或者全局队列(global queue)。这时P会唤醒一个M。P按照它的执行顺序继续执行任务。M寻找一个空闲的P,如果找得到,将G移动到它自己。然后M执行一个调度循环:调用G对象->执行->清理线程->继续寻找Goroutine。
在M的执行过程中,上下文切换随时发生。当切换发生,任务的执行现场需要被保护,这样在下一次调度执行可以进行现场恢复。M的栈保存在G对象,只有现场恢复需要的寄存器(SP,PC等),需要被保存到G对象。
如果G对象还没有被执行,M可以将G重新放到P的调度队列,等待下一次的调度执行。当调度执行时,M可以通过G的vdsoSP, vdsoPC 寄存器进行现场恢复。
scheduler
scheduler
进程 线程 协程
(1) 进程:
是资源分配的基本单位。一个进程可以包括多个线程
进程是操作系统对一个正在运行的程序的一种抽象,在一个系统上可以同时运行多个进程,而每个进程都好像在独占地使用硬件。所谓的并发运行,则是说一个进程的指令和另一个进程的指令是交错执行的。无论是在单核还是多核系统中,可以通过处理器在进程间切换,来实现单个 CPU 看上去像是在并发地执行多个进程。操作系统实现这种交错执行的机制称为上下文切换。
进程间隔离,通信问题比较麻烦.
切换成本:
虚拟内存 4G
好处
线程:
线程:是程序执行流的最小单元,是系统独立调度和分配CPU(独立运行)的基本单位。
切换成本,
好处
数据共享,同时带来坏处需要锁进行安全操作
协程:
切换成本,
数据需要锁,channel
好处
Nginx
多进程 核心是 实现多并发的核心是IO多路复用
nginx多进程好处,子进程之间独立,重启,合理利用多核
Redis
实现多并发的核心核心是IO多路复用操作内存比较快
核心单线程,顺序执行,避免了数据操作的加减锁,减少复杂度,也就是只能利用单核,
缺点 如果比较耗时的命令,会阻塞,如 KEYS,SAVE,FLUSHDB,会造成客户端超时等现象
BGSAVE 是fork一个子进程,会短暂阻塞命令线程。