4

协程概述讲解 - ZqurGy

 1 year ago
source link: https://www.cnblogs.com/zqurgy/p/17438624.html
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.
neoserver,ios ssh client

线程分为用户级线程,内核级线程和轻量级线程。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。下图可以很好说明这个形式。

3033982-20230528181823717-1461550976.png

协程状态检测

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

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

  1. 就绪状态由于这些运行体不需要设置优先级,就可以使用队列先进先出的性质;
  2. 睡眠一定会有过期时间,就可以使用定时器相关的数据结构,比如红黑树、最小堆等。
  3. 等待IO准备也是有时间的,同睡眠状态一样,使用相同的数据结构
  1. 协程是针对同步IO处理的一个组件,让同步逻辑的代码有着异步的效率;
  2. 利用IO阻塞的时间,去处理其他的事情。但是你要说它是异步也不对,它的整体代码逻辑是串行的;
  3. 协程是由运行体和调度器组成;
  4. 运行在一个线程上,针对于服务器开发,不需要为每一个客户端连接的IO创建一个线程(这种方法本身就是不对的,因为有上万个客户端,不能也创建上万个线程,对吧),让这个度比使用线程更小。

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

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

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


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK