首页 > 其他分享 >一文彻底搞懂协程(coroutine)是什么

一文彻底搞懂协程(coroutine)是什么

时间:2024-09-28 20:50:01浏览次数:7  
标签:上下文 协程 coroutine 线程 切换 搞懂 执行 CPU

什么是协程
我们可以简单的认为:协程就是用户态的线程,但是上下文切换的时机是靠调用方(写代码的开发人员)自身去控制的。

同时,协程和用户态线程非常接近,用户态线程之间的切换不需要陷入内核,但部分操作系统中用户态线程的切换需要内核态线程的辅助。

下面是一个简单的例子:

void A() {
   cout << 1 << " ";
   cout << 2 << " ";
   cout << 3 << " ";
}
 
void B() {
   cout << "x" << " ";
   cout << "y" << " ";
   cout << "z" << " ";
}
 
int main(void) {
  A();
  B();
}

在单线程中,上述函数的输出为:

1 2 3 x y z

如果我们用 libco 库将上面程序改造一下:

void A() {
   cout << 1 << " ";
   cout << 2 << " ";
   co_yield_ct();  // 切出到主协程
   cout << 3 << " ";
}
 
void B() {
   cout << "x" << " ";
   co_yield_ct();  // 切出到主协程
   cout << "y" << " ";
   cout << "z" << " ";
}
 
int main(void) {
  ...  // 主协程
  co_resume(A);  // 启动协程 A
  co_resume(B);  // 启动协程 B
  co_resume(A);  // 从协程 A 切出处继续执行
  co_resume(B);  // 从协程 B 切出处继续执行
}

同样在单线程中,改造后的程序输出如下:

1 2 x 3 y z

可以看出,切出操作是由 co_yield_ct() 函数实现的,而协程的启动和恢复是由 co_resume 实现的。函数 A() 和 B() 并不是一个执行完才执行另一个,而是产生了 “交叉执行“ 的效果,这就是通过协程实现的!

线程挺好的,我们为什么需要协程呢?

因为有些时候我们在执行一些操作(尤其是IO操作)时,不希望去做“创建一个新的线程”这种重量级的操作来异步处理。而是希望:在当前线程执行中,暂时切换到其他任务中执行,同时在IO真正准备好了之后,再切换回来继续执行!

相比于多开一个线程来操作,使用协程的好处:

  • 减少了线程的重复高频创建;

  • 尽量避免线程的阻塞;

  • 提升代码的可维护与可理解性(毕竟不需要考虑多线程那一套东西了);
    同时,下面是一些协程的特点:

  • 协程可以主动让出 CPU 时间片;(注意:不是当前线程让出 CPU 时间片,而是线程内的某个协程让出时间片供同线程内其他协程运行;)

  • 协程可以恢复 CPU 上下文;当另一个协程继续执行时,其需要恢复 CPU 上下文环境;

  • 协程有个管理者,管理者可以选择一个协程来运行,其他协程要么阻塞,要么ready,或者died;

  • 运行中的协程将占有当前线程的所有计算资源;

  • 协程天生有栈属性,而且是 lock free;

标签:上下文,协程,coroutine,线程,切换,搞懂,执行,CPU
From: https://www.cnblogs.com/java-six/p/18438384

相关文章

  • Javascript 一题搞懂 var 变量提升 & 函数声明提升!
    前置知识:在JavaScript中,“变量提升”(Hoisting)是指在代码执行之前,变量和函数声明会被提升到其所在作用域的顶部。对于使用var关键字声明的变量,会发生变量提升现象。一、声明提升1.变量声明提升:无论var变量在代码中的何处声明,它都会被提升到其所在的函数作用域......
  • 【微服务】一张图搞懂微服务架构设计
    1.前言当前,微服务架构在很多公司都已经落地实施了,下面用一张图简要概述下微服务架构设计中常用组件。不能说已经使用微服务好几年了,结果对微服务架构没有一个整体的认知,一个只懂搬砖的程序员不是一个好码农!  2.流量入口Nginx在上图中可以看到,Nginx作为整个架构的流量入......
  • 快速搞懂你是否要做深度合成算法备案
    需要备案的对象《互联网信息服务深度合成管理规定》第十九条指出,具有舆论属性或者社会动员能力的深度合成服务提供者,应当履行备案和变更、注销备案手续。这里我们要分舆论属性和社会动员能力,以及深度合成服务提供者两部分看。什么是舆论属性和社会动员能力?根据《具有舆论......
  • 一文搞懂XPath查找html dom
     博主介绍: 大家好,我是Yuperman,互联网宇宙厂经验,17年医疗健康行业的码拉松奔跑者,曾担任技术专家、架构师、研发总监负责和主导多个应用架构。技术范围: 目前专注java体系,以及golang、.Net、软件架构、DDD、微服务、redis、nginx、tomcat、mysql、oracle等业务范围: 从数字医......
  • 彻底搞懂回溯算法
    1.回溯算法的核心思想回溯算法的核心思想是:尝试+记录+回退。先尝试一种选项,在选择该选项的前提下继续寻解,如果最后寻解成功,则记录这个解,否则不用记录,然后再回退到选择该选项前的状态,改为尝试其它选项再继续寻解,判断其它选项是不是解。2.回溯算法的关键点回溯算法用于寻找全部......
  • 20年架构师用一文带你彻底搞懂SpringBoot嵌入式Web容器原理
    ContainerLess理念微服务把应用和它所依赖的组件包、配置文件及附带的运行脚本打包成一个单一、独立、可执行的jar包文件。在实现Web服务器时,几乎不需要任何配置就可以启动Tomcat。你只需要使用java-jar命令就可以让Tomcat成为SpringBoot的一个自包含的可运行组件和单元。同时,这......
  • 一文搞懂软著申请细则!
    在开发完一个系统后,若需申请软著,需要准备以下材料(模版):(一)开发合同协议https://pan.baidu.com/s/1AMj6bI7F1uiKm-qVt2g4Vw 提取码:6666(二)程序鉴别材料https://pan.baidu.com/s/1wohFGeSwyAR7jWUzDHTXgA 提取码:6666(三)文档鉴别材料https://pan.baidu.com/s/19mxZf2Fwdd2......
  • 【编程底层原理】彻底搞懂Spring是如何利用三级缓存来解决循环依赖问题的(一级缓存为
    一、整体推导思路为了彻底搞懂Spring是如何利用三级缓存来解决循环依赖问题的,要么去找三级缓存的设计者了解其设计的初衷,要么利用反推法来进行倒推(即一级缓存为啥不行,二级缓存为啥也不合适)。为了让大家能有一个更清晰的理解脉路,下面将先从反推法来介绍下一级缓存为啥不......
  • 阅读周·你不知道的JavaScript | 行为委托,搞懂对象之间的关系
    背景去年下半年,我在微信书架里加入了许多技术书籍,各种类别的都有,断断续续的读了一部分。没有计划的阅读,收效甚微。新年伊始,我准备尝试一下其他方式,比如阅读周。每月抽出1~2个非连续周,完整阅读一本书籍。这个“玩法”虽然常见且板正,但是有效,已经坚持阅读两个月。《你不知道的JavaScr......
  • Python编程 - 协程
    前言上篇文章主要讲述了python的进程,进程池和进程与线程对比等知识,接下来这篇文章再唠唠python的协程,让我们继续往下看!一、协程的使用python中的协程是一种用于处理并发任务的高效工具,它依赖于asyncio库以及async和await关键字来实现异步编程。协程与传统的多线程或......