协程

C++协程 产生背景 对于后台开发我们一个重要问题即使用尽可能少的服务器资源处理海量的请求,除了我们再架构上做多机自动扩容外,我们还必须尽可能提高单机硬件的利用率(CPU利用率+IO利用率) 为了提高硬件的利用率往往我们采用三种技术路径: 多线程 异步IO 协程 协程和异步IO以及多线程的对比 多线程 多线程可以充分利用CPU的多核,实现真正的并行,它是操作系统的基础设施。但是线程是一个粗粒度、... 阅读详情

协程Coroutines

协程是什么

image-20211204102521781

协程,Coroutines,也叫作纤程(Fiber)

协程,全称是“协同程序”,用来实现任务协作。是一种在线程中,比线程更加轻量级的存在,由程序员自己写程序来管理。

当出现IO阻塞时,CPU一直等待IO返回,处于空转状态。这时候用协程,可以执行其他任务。当IO返回结果后,再回来处理数据。充分利用了IO等待的时间,提高了效率。

一个故事说明进程、线程、协程的关系

image-20211204105438180

乔布斯想开工厂生产手机,费劲力气,制作一条生产线,这个生产线上有很多的器件以及材料。一条生产线就是一个进程。

只有生产线是不够的,所以找五个工人来进行生产,这个工人能够利用这些材料最终一步步的将手机做出来,这五个工人就是五个线程。

为了提高生产率,想到3种办法:

  1. 一条生产线上多招些工人,一起来做手机,这样效率是成倍増长,即单进程多线程方式
  2. 多条生产线,每个生产线上多个工人,即多进程多线程
  3. 乔布斯深入一线发现工人不是那么忙,有很多等待时间。于是规定:如果某个员工在等待生产线某个零件生产时 ,不要闲着,干点其他工作。也就是说:如果一个线程等待某些条件,可以充分利用这个时间去做其它事情,这就是:协程方式。

协程的核心(控制流的让出和恢复)

  1. 每个协程有自己的执行栈,可以保存自己的执行现场
  2. 可以由用户程序按需创建协程(比如:遇到io操作)
  3. 协程“主动让出(yield)”执行权时候,会保存执行现场(保存中断时的寄存器上下文和栈),然后切换到其他协程
  4. 协程恢复执行(resume)时,根据之前保存的执行现场恢复到中断前的状态,继续执行,这样就通过协程实现了轻量的由用户态调度的多任务模型

协程和多线程比较

比如,有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。阻塞在I/O操作上所花费的时间已经用灰色框标示出来了。

image-20211205151706869

  1. 在单线程同步模型中,任务按照顺序执行。如果某个任务因为I/O而阻塞,其他所有的任务都必须等待,直到它完成之后它们才能依次执行。
  2. 多线程版本中,这3个任务分别在独立的线程中执行。这些线程由操作系统来管理,在多处理器系统上可以并行处理,或者在单处理器系统上交错执行。这使得当某个线程阻塞在某个资源的同时其他线程得以继续执行。
  3. 协程版本的程序中,3个任务交错执行,但仍然在一个单独的线程控制中。当处理I/O或者其他昂贵的操作时,注册一个回调到事件循环中,然后当I/O操作完成时继续执行。回调描述了该如何处理某个事件。事件循环轮询所有的事件,当事件到来时将它们分配给等待处理事件的回调函数。

协程的优点

  1. 由于自身带有上下文和栈,无需线程上下文切换的开销,属于程序级别的切换,操作系统完全感知不到,因而更加轻量级;
  2. 无需原子操作的锁定及同步的开销;
  3. 方便切换控制流,简化编程模型
  4. 单线程内就可以实现并发的效果,最大限度地利用cpu,且可扩展性高,成本低(注:一个CPU支持上万的协程都不是问题。所以很适合用于高并发处理)

asyncio协程是写爬虫比较好的方式。比多线程和多进程都好. 开辟新的线程和进程是非常耗时的。

协程的缺点

  1. 无法利用多核资源:协程的本质是个单线程,它不能同时将 单个CPU 的多个核用上,协程需要和进程配合才能运行在多CPU上。
  2. 当然我们日常所编写的绝大部分应用都没有这个必要,除非是cpu密集型应用。

使用yield实现协程(已淘汰,了解即可)

Python中的协程经历了很长的一段发展历程。其大概经历了如下三个阶段:

  1. 最初的生成器变形yield/send
  2. 引入@asyncio.coroutine和yield from
  3. Python3.5版本后,引入async/await关键字

【示例】不使用协程执行多个任务

#coding=utf-8
import time
​
def func1():
  for i in range(3):
    print(f'北京:第{i}次打印啦')
    time.sleep(1)
  return "func1执行完毕"

def func2():
  for k in range(3):
    print(f'上海:第{k}次打印了' )
    time.sleep(1)
  return "func2执行完毕"
​
def main():
  func1()
  func2()

if __name__ == '__main__':
  start_time = time.time()
  main()
  end_time = time.time()
  print(f"耗时{end_time-start_time}")  #不使用协程,耗时6秒
​
'''
执行结果:
北京:第0次打印啦
北京:第1次打印啦
北京:第2次打印啦
上海:第0次打印了
上海:第1次打印了
上海:第2次打印了
耗时6.042387008666992
'''

 【示例】使用yield协程,实现任务切换

#coding=utf-8
import time

def func1():
  for i in range(3):
    print(f'北京:第{i}次打印啦')
    yield       # 只要方法包含了yield,就变成一个生成器, 开始执行func2
    time.sleep(1)

def func2():
  g = func1()   # func1是一个生成器,func1()就不会直接调用,需要通过next()或for循环调用
  print(type(g))
  for k in range(3):
    print(f'上海:第{k}次打印了' )
    next(g)     # 转换执行func1的代码
    time.sleep(1)

#有了yield,我们实现了两个任务的切换+保存状态
if __name__ == '__main__':
  start_time = time.time()
  func2()
  end_time = time.time()
  print(f"耗时{end_time-start_time}")  #耗时5.0秒,效率差别不大

'''
执行结果:

上海:第0次打印了
北京:第0次打印啦
上海:第1次打印了
北京:第1次打印啦
上海:第2次打印了
北京:第2次打印啦
耗时5.039638996124268
'''

asyncio实现协程(重点)

  1. 正常的函数执行时是不会中断的,所以你要写一个能够中断的函数,就需要加async
  2. async 用来声明一个函数为异步函数,异步函数的特点是能在函数执行过程中挂起,去执行其他异步函数,等到挂起条件(假设挂起条件是sleep(5))消失后,也就是5秒到了再回来执行
  3. await 用来用来声明程序挂起,比如异步程序执行到某一步时需要等待的时间很长,就将此挂起,去执行其他的异步程序。
  4. asyncio是python3.5之后的协程模块,是python实现并发重要的包,这个包使用事件循环驱动实现并发。

使用asyncio,整体执行完,耗时3秒,效率极大提高。

【示例】asyncio异步IO的典型使用方式

#coding=utf-8
import asyncio
import time

async def func1():   #async表示方法是异步的
  for i in range(3):
    print(f'北京:第{i}次打印啦')
    await asyncio.sleep(1)
  return "func1执行完毕"

async def func2():
  for k in range(3):
    print(f'上海:第{k}次打印了' )
    await asyncio.sleep(1)
  return "func2执行完毕"

async def main():
  res = await asyncio.gather(func1(), func2())
  #await异步执行func1方法
  #返回值为函数的返回值列表,本例为["func1执行完毕", "func2执行完毕"]
  print(res)

if __name__ == '__main__':
  start_time = time.time()
  asyncio.run(main())
  end_time = time.time()
  print(f"耗时{end_time-start_time}")  #耗时3秒,效率极大提高

 

Kotlin协程详解——协程基础 你通常会看到 runBlocking 在应用程序的最顶层被这样使用,而在真正的代码中却很少见到它的身影,因为线程是宝贵的资源,阻塞它们是低效的,而且通常是不被期望的。协程遵循结构化并发的原则,这意味着新的协程只能在特定的 CoroutineScope 内启动,该作用域限定了协程的生命周期。这些情况导致的问题是代码间的嵌套层级太深,导致逻辑嵌套复杂,后续的维护成本也要提高,这不是我们所要看到的。协程可以被视为轻量级的线程,但它们之间存在一些重要的区别,这使得它们在实际使用中与线程有很大的不同。 阅读详情

相关推荐

深入浅出c++协程丨C++协程实现

1|0一些实现的c++协程 C++协程实现相关视频讲解:(视频代码资料点击 正在跳转 获取) 协程的实现与原理剖析(上) 协程的实现与原理剖析(下) 协程是一种函数对象,可以设置锚点做暂停,然后再该锚点恢复继续运行,我觉得这是最合适的定义,用户态线程,轻量级线程,可中断恢复的函数,这些都不够精确,先来认识一个boost 1.75的一个例子 #include <iostream> #include <boost/coroutine2/all.hpp> void cor

Linuxhus的博客 2078

Python异步编程入门

带你初步认识Python异步编程模型

千山暮彩 1451

C#协程

Unity中协程的执行原理 UnityGems.com给出了协程的定义: A coroutine is a function that is executed partially and, presuming suitable conditions are met, will be resumed at some point in the future ...

祝你万事顺利的博客 5701

python asyncio 异步 I/O - 协程(Coroutine)与运行

前言 Python 在 3.5 版本中引入了关于协程的语法糖 async 和 await, 在 python3.7 版本可以通过 asyncio.run() 运行一个协程。 所以建议大家学习协程的时候使用 python3.7+ 版本,本文示例代码在 python3.8 上运行的。 协程 coroutines 协程(coroutines)通过 async/await 语法进行声明,是编写 asyncio 应用的推荐方式。 例如,以下代码段(需要 Python 3.7+) import asyncio impo

qq_27371025的博客 1763

这就是协程

本文介绍了协程的基本概念和实现原理。协程是一种可暂停和恢复的用户态轻量级线程,其调度由用户程序控制。文章比较了有栈与无栈协程的区别,并分析了对称/非对称协程的特点。重点阐述了基于Linux ucontext族函数的非对称独立栈协程实现方案,包括协程状态管理、栈空间分配、上下文切换等核心机制。通过封装协程入口函数,实现了协程结束时自动yield的功能。文中还提供了协程重置方法,支持复用已结束协程的栈空间。该实现方案采用非对称设计,通过resume/yield方法进行控制权转移,简化了协程间的调度逻辑。

b_i_n_03的博客 1187

协程嵌套子协程

分析一段代码后,就能弄懂了: import asyncio async def think(): print('盘算这生意靠不靠谱,思考一段时间后,将结果直接告知调用方event loop......') await asyncio.sleep(2.0) async def compute(x, y): print("event loop联系到子协程Compute ...

hubing的博客 1458

Python 协程 - Coroutines

1 协程 - Coroutines 2 3 Awaitable Objects, 4 Awaitable Objects 通常由 __await__() 生成, 而 5 Coroutine objects 是由 async def 关键字定义的函数 return 的 Awaitable Objects. 6 Note, 7 被...

weixin_30505751的博客 197

基于云风协程库的协程原理解读

协程原理 云风的协程库实现 保存现场 恢复现场 打造业务零入侵的自用协程库(待续) 协程原理 协程的本质都是通过修改 ESP 和 EIP 指针来实现的。其理论上还是单线程在运行,要想实现真正的并发,其实是需要多个CPU才能的。并发是并行的充分条件,并发是在程序级别上实现的,而并行是在机器级别上实现的,要想实现并行,程序上必须以并发实现,但是程序上实现了并发...

Odew 2640

Python—协程(Coroutine)

协程概念和代码使用

蓝魔的博客 6279

Python之协程Coroutines

当出现IO阻塞时,CPU一直等待IO返回,处于空转状态。比如,有3个任务需要完成,每个任务都在等待I/O操作时阻塞自身。协程,全称是“协同程序”,用来实现任务协作。基于yield并发执行,多任务之间来回切换,这就是个简单的协程的体现,但是他能够节省I/O时间吗?只有生产线是不够的,所以找五个工人来进行生产,这个工人能够利用这些材料最终一步步的将手机做出来,乔布斯想开工厂生产手机,费劲力气,制作一条生产线,这个生产线上有很多的器件以及材料。使用asyncio,整体执行完,耗时3秒,效率极大提高。

Calor13的博客 335

《商用密码应用与安全性评估》第四章密码应用安全性评估实施要点4.1密码应用方案设计

密码应用方案设计

qq_40442137的博客 1472

有栈协程与无栈协程

引言 关于协程是什么这类基本概念我们不再多提,有兴趣的朋友可以看看我写的这篇文章《聊聊协程》。写这篇文章的原因是当我对这个问题感到疑惑的时候发现优快云上并没有相关的文章,遂在有了一点理解以后想写下一点对这个问题的看法,以帮助后来学习的朋友。 正文 如今虽不敢说协程已经是红的发紫,但确实是越来越受到了大家的重视。Golang中的已经是只有goroutine,以至于很多go程序员是只知有协程,不知有线程了。就连C++这样的“老顽固”也在最新的C++20中原生支持协程。更不用说很多活跃的语言如python,ja

李兆龙的博客 1万+

单细胞基因可视化之热图的根本改造2

我们前面已经说过了单细胞marker/或者其他任意基因的热图的简单修饰(单细胞基因可视化之热图改造修饰1),仅仅是基于颜色和DoHeatmap函数的参数修饰。那么要对热图进行根本的改造,关键点在于提取表达矩阵,然后对分组进行注释,就可以使用heatmap或者ComplexHeatmap来做图了。 首先计算marker基因,然后选择自己需要展示的基因。 library(Seurat) library(stringr) library(dplyr) all.markers <- Find

qq_42090739的博客 6676

Kotlin协程:协程的基础与使用

协程是Coroutine的中文简称,co表示协同、协作,routine表示程序。协程可以理解为多个互相协作的程序。协程是轻量级的线程,它的轻量体现在启动和切换,协程的启动不需要申请额外的堆栈空间;协程的切换发生在用户态,而非内核态,避免了复杂的系统调用。...

LeeDuoZuiShuai的博客 1万+

腾讯大佬总结的170道 python面试题

简述基于 TCP 协议的套接字通信流程。19.面向对象中`__new__` 和 `__init__` 区别。86. 解释 Python 中的`//`,`%`和`**`运算符。45.isinstance 的作用以及与 type()的区别。3. 简述下 Python 中的字符串、列表、元组和字典。143. 如何高效的找到 redis 中的某个 KEY。140. 如何保证 redis 中的数据都是热点数据。147. redis 中的 watch 的命令的作用。108. 简述 进程、线程、协程的区别以及应用场景。

AudiA6LV6的博客 488

Netapp FAS2750热备盘替换失败问题分析与解决

本文深入分析了Netapp FAS2750存储系统中热备盘替换失败的故障现象,揭示了磁盘分区属主不匹配导致数据同步无法启动的根本原因。通过详细的排查步骤和解决方案,帮助运维人员快速恢复aggr状态,并提供了长期预防措施和最佳实践建议,确保存储系统的高可用性。

weixin_33737774的博客 399

协程的概念,为什么要用协程,以及协程的使用

什么是协程 协程, 又称为微线程,是一种用户态的轻量级线程。协程不像线程和进程那样,需要进行系统内核上的上下文切换,协程的上下文切换是由开发人员决定的。 协程是一种用户级的轻量级线程。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈。因此: 协程能保留上一次调用时的状态(即所有局部状态的一个特定组合),每次过程重入时,...

weixin_44575037的博客 2万+

MDM主数据清洗和编码集成说明

绝大多数的企业业务系统是伴随业务发展而建设的,但随着业务发展单一系统难以支撑企业业务闭环。MDM主数据管理平台可以满足企业数据治理的需求,本文针对主数据清洗和编码集成进行梳理。...

数通畅联 3319

【协程库】协程类,协程的创建,协程的切换,协程的入口以及协程的重置

协程类,协程的创建,协程的切换,协程的入口以及协程的重置

weixin_45962681的博客 1239

Simulink仿真模块 - Signal Conversion

目录 说明 实例 创建总线信号的连续副本 ​将虚拟总线转换为非虚拟总线​ 将非虚拟总线转换为虚拟总线 将Muxed信号转换为矢量 模块特性 Signal Conversion:将信号转换为新类型,而不改变信号值 在仿真库中的位置为: Simulink / Signal Attributes HDL Coder / Signal Attributes 模型为: 说明 Signal Conversion模块可将信号从一种类型转换为另一种类型。要选择要...

jk_101的博客 3421

Qt C++ HTTP 调用通义千问大模型 X 学术论文润色工具(SCI 格式适配)

请求地址:`https://dashscope.aliyuncs.com/api/v1/services/aigc/text-generation/generation`;| Windows | 打包时携带 `Qt6Network.dll`/`libcrypto-1_1-x64.dll` 等依赖;| Linux | 安装 `libssl-dev` 和 `libcurl4-openssl-dev`;| API 调用失败 | 检查 API-KEY 是否有效;

寒寒豆豆软件公司的博客 104

【Kotlin】协程

相较于 C# 中的协程(详见 →),Kotlin 中协程更灵活,难度更大。协程是一种并发设计模式,用于简化异步编程,它允许以顺序化的方式表达异步操作,避免回调地狱等问题。使用协程,可以将异步操作的代码像同步代码一样写,而无需显式地管理线程。在 Kotlin 中,协程由 kotlinx.coroutines 库提供支持。它使用 suspend 修饰符来标记挂起函数(即可暂停执行并稍后恢复执行的函数),这使得编写异步代码更加直观和简单。协程和线程具有以下异同点。

little_fat_sheep 2391

YOLOv13优化Faster_Block:卷积(Partial Convolution)、多层感知机(MLP)结构和残差连接

Faster_Block 代表了现代深度学习中效率与性能平衡的一个典型案例。它通过部分卷积技术巧妙地减少了计算开销,同时通过精心设计的架构保持了强大的特征学习能力。这种设计思想对于移动端部署、实时应用和大规模模型训练都具有重要意义。 未来的发展方向可能包括更智能的动态分割策略、与新兴硬件的深度适配,以及与其他先进技术(如自注意力机制、神经架构搜索等)的结合。Faster_Block 的成功展示了在深度学习领域,创新往往来自于对问题本质的深刻理解和巧妙的工程实现。

FJN110的博客 427

Kotlin 协程一 —— 协程 Coroutine

Go、Python 等很多变成语言在语言层面上都实现协程,java 也有三方库实现协程,只是不常用, Kotlin 在语言层面上实现协程,对比 java, 主要还是用来解决异步任务线程切换的痛点。 协程基于线程,但相对于线程轻量很多,可理解为在用户层模拟线程操作; 每创建一个协程,都有一个内核态线程动态绑定,用户态下实现调度、切换,真正执行任务的还是内核线程。 线程的上下文切换都需要内核参与,而协程的上下文切换,完全由用户去控制,避免了大量的中断参与,减少了线程上下文切换与调度消耗的资源。

金戈鐡馬 5485

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

Kotlin协程 — 子协程中无法进行IO、网络请求等并发

⼦协程 : 当⼀个协程被其它协程在 CoroutineScope 中启动的时候,它将通过CoroutineScope.coroutineContext 来承袭上下⽂,并且这个新协程的 Job 将会成为⽗协程作业的⼦作业。当⼀个⽗协程被取消的时候,所有它的⼦协程也会被递归的取消。 然⽽,当 GlobalScope 被⽤来启动⼀个协程时(顶层协程),它与作⽤域⽆关且是独⽴被启动的⼦协程 。 下面有个例...

喝烧酒的兔子 3245

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

kotlin协程入门

可以简单地将它理解成一种轻量级的线程。我们之前所学习的线程是非常重量级的,它需要依靠操作系统的调度才能实现不同线程之间的切换。而使用协程却可以仅在编程语言的层面就能实现不同协程之间的切换,从而大大提升了并发编程的运行效率。为什么使用协程?简洁性:协程使得异步代码看起来像同步代码,减少了回调地狱的问题。轻量级:协程比线程更轻量,可以在同一线程中运行多个协程。易于管理:协程可以通过结构化并发来管理生命周期,避免内存泄漏和资源浪费。

weixin_63357306的博客 1304

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

上一篇: 进程
下一篇: 【无标题】
可爱软萌喵酱
博客等级 码龄5年 100粉丝 20原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值