协程是什么?怎么来的?它有什么作用?

  • Post author:
  • Post category:其他





前言


该文章为我参考网上一些文章、网友回答后拼凑整理得来。




一、协程是什么?


百度百科:协程(Coroutines)不是进程或线程,其执行过程更类似于子例程,或者说不带返回值的函数调用。

协程是什么?



二、协程是怎么来的?


没有啥复杂的东西,考虑清楚需求,就可以很自然的衍生出这些解决方案。

一开始大家想要同一时间执行那么三五个程序,大家能一块跑一跑。特别是UI什么的,别一上计算量比较大的玩意就跟死机一样。于是就有了

并发

,从程序员的角度可以看成是多个独立的逻辑流。内部可以是多cpu并行,也可以是单cpu时间分片,能快速的切换逻辑流,看起来像是大家一块跑的就行。

但是一块跑就有问题了。我计算到一半,刚把多次方程解到最后一步,你突然插进来,我的中间状态咋办,我用来储存的内存被你覆盖了咋办?所以跑在一个cpu里面的并发都需要处理上下文切换的问题。

进程

就是这样抽象出来个一个概念,搭配虚拟内存、进程表之类的东西,用来管理独立的程序运行、切换。

后来一电脑上有了好几个cpu,好咧,大家都别闲着,一人跑一进程。就是所谓的

并行

因为程序的使用涉及大量的计算机资源配置,把这活随意的交给用户程序,非常容易让整个系统分分钟被搞跪,资源分配也很难做到相对的公平。所以核心的操作需要陷入内核(kernel),切换到操作系统,让老大帮你来做。

有的时候碰着I/O访问,阻塞了后面所有的计算。空着也是空着,老大就直接把CPU切换到其他进程,让人家先用着。当然除了I\O阻塞,还有时钟阻塞等等。一开始大家都这样弄,后来发现不成,太慢了。为啥呀,一切换进程得反复进入内核,置换掉一大堆状态。进程数一高,大部分系统资源就被进程切换给吃掉了。后来搞出

线程

的概念,大致意思就是,这个地方阻塞了,但我还有其他地方的逻辑流可以计算,这些逻辑流是共享一个地址空间的,不用特别麻烦的切换页表、刷新TLB,只要把寄存器刷新一遍就行,能比切换进程开销少点。

如果连时钟阻塞、 线程切换这些功能我们都不需要了,自己在进程里面写一个逻辑流调度的东西。那么我们即可以利用到并发优势,又可以避免反复系统调用,还有进程切换造成的开销,分分钟给你上几千个逻辑流不费力。这就是

用户态线程

从上面可以看到,实现一个用户态线程有两个必须要处理的问题:一是碰着阻塞式I\O会导致整个进程被挂起;二是由于缺乏时钟阻塞,进程需要自己拥有调度线程的能力。如果一种实现使得每个线程需要自己通过调用某个方法,主动交出控制权。那么我们就称这种用户态线程是协作式的,即是

协程


作者:阿猫 链接:https://www.zhihu.com/question/20511233/answer/24260355 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。




三、协程的好处有哪些?

协程是进程和线程的升级版,进程和线程都面临着内核态和用户态的切换问题而耗费许多切换时间,而协程就是

用户自己控制切换的时机,不再需要陷入系统的内核态



协程的

执行效率非常高

。因为子程序切换不是线程切换,而是由程序自身控制。因此,

没有线程切换的开销

,和多线程相比,线程数量越多,相同数量的协程体现出的优势越明显。


不需要多线程的锁机制

。由于只有一个线程,也不存在同时写变量的冲突,在协程中控制共享资源不需要加锁,只需要判断数据的状态,所以执行效率远高于线程。对于多核CPU可以使用多进程+协程来尽可能高效率地利用CPU。




总结


本质上协程就是用户空间下的线程。

在这里插入图片描述

虽然协程的概念很早就有,但是很长一段时间,主流的编程语言都没有提供对协程的原生支持,它只出现在一些小众语言中(Simula 和 Modula-2等)。后来出现的纤程啦、coroutine啦都是协程的具体实现,但是都没有达到现在的热度!

直到高并发成为主流趋势,瞬间涌入的海量请求,让多进程模型下,内存资源“捉襟见肘”;让多线程模型下,“用户态”“内核态”两头忙,却依然疲于应对!

而协程这种既轻量又灵活的,由用户态进行调度的多任务模型,便获得了广泛的关注。越来越多的编程语言提供了对协程的支持,而真正让协程大放异彩的,是它在IO多路复用中的应用!

在这里插入图片描述




版权声明:本文为weixin_48475611原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。