• 协程概述讲解


    协程

    线程分为用户级线程,内核级线程和轻量级线程。Linux中使用的是轻量级线程,而协程虽然是运行在线程之上,但是是run在用户空间。并且协程和线程一样,拥有自己的调度器、cpu的上下文切换等。

    协程在我个人看来是一种用户级线程;

    • 这是因为对于cpu有上下文的切换,而且是在用户空间的层次进行数据处理;一旦被内核的代码阻塞,是无法进行解除阻塞状态;

    协程的功能

    首先需要明确一点,协程是干嘛的,针对的事物是什么?

    • 协程针对的是IO处理,可以将多个同步关系的IO处理的性能接近于异步IO的效率;
    • 这样既保证了编写代码的逻辑,又保证了代码执行的效率;

    异步IO的效率高,是正常的,因为调用某个IO函数,也就是系统调用,根据异步IO模型中的描述,它不会被阻塞且处理完毕后会通知调用线程,也就是异步IO模型没有阻塞时间

    协程的做法

    那么问题就来了,应该是一个什么样的逻辑处理同步IO,才能让其性能接近异步IO呢?

    • 消除同步IO被阻塞住时的等待时间,从而让效率无限接近于异步IO。
    • 这就是协程干的功能,一旦被阻塞住了,就会把cpu让出给其他可以执行的协程。

    cpu切换上下文过程

    协程由运行体调度器组成。

    协程的运行体中保存着让出后的寄存器状态,方便于之后恢复、子过程函数和其参数、自身协程的状态、栈的大小等;

    也就引出了yeild和resume这两个功能

    • yeild的中文名叫让出,cpu每个时刻只能运行一个操作(),让出操作会让当前cpu的寄存器空出给其他协程运行体(函数)使用
    • resume的中文名叫恢复,cpu空出后,恢复之前协程运行体(函数)执行的位置。

    由于讨论的是一个线程的操作,不会出现内核切换线程的操作。

    接下来要说是调度器,使用yeild和resume两个操作,进行切换协程。使用协程A->调度器->协程B这种形式的切换,而不是协程A->协程B。下图可以很好说明这个形式。

    协程状态检测

    协程调度器在调度协程运行体的时候就需要维护协程所具有的状态,比如就绪、等待、睡眠。

    这也就需要一些数据结构进行维护这些运行体。

    1. 就绪状态由于这些运行体不需要设置优先级,就可以使用队列先进先出的性质;
    2. 睡眠一定会有过期时间,就可以使用定时器相关的数据结构,比如红黑树、最小堆等。
    3. 等待IO准备也是有时间的,同睡眠状态一样,使用相同的数据结构

    总结

    1. 协程是针对同步IO处理的一个组件,让同步逻辑的代码有着异步的效率;
    2. 利用IO阻塞的时间,去处理其他的事情。但是你要说它是异步也不对,它的整体代码逻辑是串行的;
    3. 协程是由运行体和调度器组成;
    4. 运行在一个线程上,针对于服务器开发,不需要为每一个客户端连接的IO创建一个线程(这种方法本身就是不对的,因为有上万个客户端,不能也创建上万个线程,对吧),让这个度比使用线程更小。

    扩展

    至于它和reactor进行对比,它俩的性能差距不会很大。

    协程相比于reactor,reactor的回调函数太过于分散,不易代码可读。

    reactor其实是对事件进行一个异步的处理,于此同时也不需要看到IO处理的逻辑,只需要关注每一个事件应该怎么做。

  • 相关阅读:
    CAPL如何对以太网报文的长度字段和校验和字段设置错误值
    细胞膜仿生修饰树枝状聚酰胺-胺PAMAM/细胞膜修饰超声造影剂/介孔硅
    tensorflow内存泄漏或模型只加载不运行
    ARPG----C++学习记录03 Section7位置,偏移,函数
    # Python基础:输入输出详解-读写文件(还需完善)
    Vscode配置已有工程及自动格式化
    python机器人编程——垃圾自动分类,在VREP环境中,UARM与摄像头联动,实现基于视觉识别的自动抓取(下)
    十、面向对象 之 多态
    Java常见注解及其使用汇总
    (c语言进阶)数据存储——浮点型存储
  • 原文地址:https://www.cnblogs.com/zqurgy/p/17438624.html