Golang 协程是什么

159 阅读2分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Golang 协程是什么

线程

我们都知道,线程是进程中的执行体,拥有一个执行路口,以及从进程虚拟地址空间中分配的栈。包括用户栈和内核栈。 操作系统会记录线程控制信息,而线程获得CPU时间片以后才可以执行。CPU的栈指针、指令指针等寄存器,都要切换到对应的线程。

在这里插入图片描述

协程

如果线程自己又创建几个执行体,给他们各自指定执行入口,申请一些内存给它们用做执行栈,那么线程就可以按需调度这几个执行体了。为了实现这些执行体的切换,线程也需要记录它们的控制信息。包括ID栈的位置执行入口地址执行现场等等。 线程可以选择一个执行体来执行,此时CPU中指令指针就会指向这个执行体的入口,栈基和栈指针寄存器也会指向线程给它分配的执行栈。

切换执行体

要切换执行体时,需要先保存当前执行体的执行现场,然后切换到另一个执行体。通过同样的方式,可以恢复到之前的执行体,这样就可以从上次中断的地方继续执行。 这些由线程创建的执行体就是所谓的协程。 因为用户程序不能操作内核空间,所以只能给协程分配用户栈,而操作系统对用户栈一无所知。所以协程又被称为用户态线程

在这里插入图片描述

协程思想的关键

在创建协程时,都要指定执行入口,底层都会分配协程执行栈和控制信息,否则又该如何实现用户态调度? 而让出执行权时,也都要保存执行现场,不然如何能从中断处恢复执行? 所以协程思想的关键在于控制流的主动让出恢复,每个协程拥有自己的执行栈,可以保存自己的执行现场。所以可以由用户程序,按需创建协程。

协程的主动让出和恢复执行

协程主动让出执行权时,会保存执行现场,然后切换到其它协程。 协程恢复执行时,会根据之前保存的执行现场,恢复到中断前的状态,继续执行。 这样,就通过协程实现了既轻量又灵活的、由用户态进行调度的多任务模型

在这里插入图片描述

真正让协程大放异彩的是它在IO多路复用中的应用,二者的结合是一种炙手可热的高并发解决方案。

在这里插入图片描述