为什么会有协程
普通的应用程序编写,在c++最多的实现方式是多线程来实现异步操作
多线程存在的问题
1、多线程切换带来的线程用户台到内核态的开销增大
2、多线程要解决资源竞争问题。
3、异步编程业务逻辑不在一起,对代码的理解及阅读不友好。
而有没有一种方式,能够实现用同步的方式,实现异步的性能,go语言中有原生的协程。所以go语言编写网络程序有天生的优势,c++20提出语言上支持协程,但是目前大多数人使用的可能还是c++11,所以目前要在c++中实现协程,就需要自己造轮子。
协程能解决的问题
1、协程用同步的方式解决来实现异步的效率
2、协程同步的好处是逻辑清晰,没有线程资源竞争
协程实现方式:
协程原语
create:创建,跟线程一样,需要指定协程的执行函数,属性和参数。
yield:让出,意思是当前的协程让出cpu给到调度器。
resume:意思是启动协程或者是恢复协程 。
假设有两个IO操作的阻塞任务,
任务1执行完,让出(yield)资源,调度器调度任务2 resume,任务2等待IO操作时让出cpu给调度器。所以,如果多任务是带IO操作的,则适合使用协程,如果是纯粹的计算cpu密集型服务,则不适用协程,因为如果是cpu密集型,会导致任务一直不让出,另外的任务也得不到cpu的资源,所以不适合。
实现协程有几种方式:
1、longJump/setjump
2、使用ucontext
3、使用汇编代码来实现跳转。
大多数协程框架都是使用了第三种方式,包括我们上面提到的libgo,libco,libaco都是,也就是用汇编来实现协程的栈切换。
协程需要知道的前备知识
1、汇编语言与寄存器
2、栈,堆的内存分布,函数调用的入栈,出栈,用堆如何来保存栈,内存对齐
3、hook钩子函数的实现原理
4、阻塞IO,非阻塞IO,epoll,poll等基本知识。
5、时间轮定时器的实现,可以基于红黑树或其他方法。
6、有两种保存栈的方式,独立栈和共享栈两种模式。
下一个文章将开始分享libco的实现,其会涉及到的以上的相关的知识,我会尽量的都详细讲解。