协程和线程

news/发布时间2024/5/14 14:27:53

文章目录

    • 什么是线程和协程?
    • 协程和线程的主要区别
    • 协程简单示例
      • 问题

什么是线程和协程?

线程(Thread)和协程(Coroutine)都是为了实现多任务并发处理的编程概念,但它们的实现方式和功能有所不同。

线程:线程是操作系统能够进行运算调度的最小单位。
它被包含在进程中,是进程中的实际运行单位。每个线程都拥有独立的运行栈和程序计数器,并共享同一进程中的各种系统资源如虚拟地址空间初始化代码等。线程之间的切换由操作系统来控制,因此称为内核级别的线程。

协程:协程可以理解为轻量级的线程,也称微线程、纤程。
协程的调度完全由用户程序自控行,称为用户级别的线程。一个程序中的协程,可以象征性的看成一个个独立的小线程,它们之间可以彼此协作,共同完成任务。进入和退出协程的操作相对于线程来说资源开销小的多。

协程和线程的主要区别

管理者:线程是由操作系统管理和调度的,而协程则是由程序代码自身进行管理和调度。也就是说,如果你创建了一个线程,那么何时切换到这个线程、何时切换出这个线程这些决定都是由操作系统来做的。而如果你创建一个协程,那么你需要在代码里显示地指定何时切换任务。

开销:创建和切换线程存在一定的系统调用和上下文切换开销,需要耗费较大的资源,比如保存和恢复线程的执行现场(即线程的一些运行状态),效率较低。而创建和切换协程直接操作内存,没有系统调用的开销,开销则小得多,因此效率较高。所以相比之下,协程能更高效地用于大量的并发任务。

阻塞:当一个线程在等待某些资源,例如磁盘IO或者网络数据时,操作系统会切换到其他线程继续工作,这时原来的线程就处于阻塞状态。而协程则可以主动放弃控制权,转而执行其他的协程任务,这就避免了因为等待资源造成的阻塞,提高了程序的运行效率。

控制:由于线程的调度由操作系统自动完成,程序对其具体的执行流程控制较弱。而协程由程序自身控制其切换,因此程序对协程的控制更为精确。

线程可以同时多个运行,协程在任意时刻只能运行一个,其他处于暂停状态。

协程简单示例

Python中的协程示例:

import asyncioasync def count():print("One")await asyncio.sleep(1)print("Two")async def main():await asyncio.gather(count(), count(), count())asyncio.run(main())

这个示例中,我们创建了一个名为count的协程。这个协程先打印"one",然后等待1秒,再打印"Two"。注意到await关键字,它告诉Python暂停执行count协程,转而去执行其他的任务,在这里就是等待1秒。过了1秒之后,Python会回到被暂停的count协程,继续执行,打印出"Two"。

main协程中,我们用到了asyncio.gather函数,并同时运行了三个count协程。如果没有用到协程,程序打印One和Two之间都需要等待1秒。但是在这个例子中,程序会先打印出三个"One",然后等待1秒,再打印出三个"Two"。

asyncio.run(main())这行代码就是启动整个程序。

可以看到,通过使用协程,我们的程序可以在等待某个任务完成的期间,并发地执行其他的任务,提高了程序的效率。这就体现了协程的重要价值之一。


问题

线程可以同时多个运行,协程在任意时刻只能运行一个,为什么说上面的例子中同时运行了三个count协程?

在回答这个问题之前,我们首先需要明确一点,即协程虽然在任意时刻只能运行一个,但是可以在任何一个协程中主动放弃执行权,将控制权交回给主调度程序(在Python中通常是某种事件循环,如 asyncio.get_event_loop()),然后主调度程序再根据一定的规则选择下一个协程执行。

特别地,当一个协程遇到IO等待(比如网络请求、磁盘读写等)的时候,它会主动放弃执行权,这样主调度程序就可以在一个协程等待的时候执行其他协程,从而实现了并发。

'asyncio.gather(count(), count(), count())'是并发地运行三个 count 协程。这并不是说这三个协程真正意义上并行(同时)运行,而是说明:当一个 count 协程执行到 ‘await asyncio.sleep(1)’ 这行代码时,会主动放弃执行权,然后事件循环就去执行下一个还未进入睡眠的 count 协程,这样循环下去就实现了这三个 count 协程的并发。

因此,我们看到"程序会先打印出三个’One’,然后等待1秒,再打印出三个’Two’"其实就是Python的协程调度机制执行的结果。每个count协程在执行到 ‘await asyncio.sleep(1)’ 这行代码后,由于’await’关键字的存在,都会主动放弃执行权,然后执行下一个 count 协程,当所有的 count 协程都放弃了执行权进入了睡眠后,主调度程序(事件循环)就静静等待一秒,一秒后再唤醒这三个 ‘count’ 协程,继续执行它们之后的代码。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.bcls.cn/aaaM/4789.shtml

如若内容造成侵权/违法违规/事实不符,请联系编程老四网进行投诉反馈email:xxxxxxxx@qq.com,一经查实,立即删除!

相关文章

Redis持久化

Redis持久化 Redis持久化方式 RDB快照 在默认情况下,Redis将内存数据库快照保存在名字为dump.rdb的二进制文件中 save 60 1000 表示60s内有1000次命令,我们关闭RDB只需要将所有的save保存注释掉即可 我们还可以手动执行命令生成RDB快照,进…

2023年总结与2024展望

今天是春节后上班第一天,你懂的,今天基本上是摸鱼状态,早上把我们负责的项目的ppt介绍完善了一下,然后写了一篇技术文章,《分布式系统一致性与共识算法》。接着就看了我近几年写的的年度总结,我一般不会在元…

从软硬件以及常见框架思考高并发设计

目录 文章简介 扩展方式 横向扩展 纵向扩展 站在软件的层面上看 站在硬件的层面上看 站在经典的单机服务框架上看 性能提升的思考方向 可用性提升的思考方向 扩展性提升的思考方向 文章简介 先从整体,体系认识,理解高并发的策略,方…

时序预测 | Matlab实现基于GRNN广义回归神经网络的光伏功率预测模型

文章目录 效果一览文章概述源码设计参考资料效果一览 文章概述 1.时序预测 | Matlab实现基于GRNN广义回归神经网络的光伏功率预测模型 2.单变量时间序列预测; 3.多指标评价,评价指标包括:R2、MAE、MBE等,代码质量极高; 4.excel数据,方便替换,运行环境2020及以上。 广义回…

pulsar入门介绍

概述 Pulsar 是一个多租户、高性能的服务器到服务器消息传递解决方案。Pulsar 最初由 Yahoo 开发,由 Apache 软件基金会管理。 特点 Pulsar 的主要功能如下: 原生支持 Pulsar 实例中的多个集群,可跨集群无缝地复制消息。非常低的发布和端…

C语言中关于#include的一些小知识

写代码的过程中,因为手误,重复包含了头文件 可以看到没有报错 如果是你自己编写的头文件,那么如果没加唯一包含标识的话,那么编译器会编译报错的。如果是系统自带的头文件,由于其每个头文件都加了特殊标识&#xff0c…

【数据结构】排序(2)

目录 一、快速排序: 1、hoare(霍尔)版本: 2、挖坑法: 3、前后指针法: 4、非递归实现快速排序: 二、归并排序: 1、递归实现归并排序: 2、非递归实现归并排序: 三、排序算法…

MCU多核异构通信原理

摘要: 本文结合瑞萨RZ/G2L 多核处理器,给大家讲述一下多核异构设计及通信的原理。 随着电子技术的不断发展,以及市场需求的日益增长,嵌入式系统不仅要求执行复杂的控制任务,还需要实时地采集和处理数据。 为了满足这…

QEMU源码全解析 —— virtio(22)

接前一篇文章:QEMU源码全解析 —— virtio(21) 前几回讲解了virtio驱动的加载。本回开始讲解virtio驱动的初始化。 在讲解virtio驱动的初始化之前,先要介绍virtio配置的函数集合变量virtio_pci_config_ops。实际上前文书也有提到…

【wails】(6):使用wails做桌面应用开发,使用gin+go-chatglm.cpp进行本地模型运行,在windows上运行成功

1,整体架构说明 主要使用,参考的开源项目是: https://github.com/wailsapp/wails 前端项目: https://github.com/Chanzhaoyu/chatgpt-web 运行模型: https://github.com/Weaxs/go-chatglm.cpp 参考代码: h…

四、分类算法 - 随机森林

目录 1、集成学习方法 2、随机森林 3、随机森林原理 4、API 5、总结 sklearn转换器和估算器KNN算法模型选择和调优朴素贝叶斯算法决策树随机森林 1、集成学习方法 2、随机森林 3、随机森林原理 4、API 5、总结

高频面试题整理(一)

文章目录 平台无关性如何实现?JVM如何加载 .class文件?什么是反射?谈谈ClassLoader谈谈类的双亲委派机制类的加载方式Java的内存模型?JVM内存模型-jdk8程序计数器:Java虚拟机栈局部变量表和操作数栈: Java内存模型中堆和栈的区别…

第四十二回 假李逵翦径劫单身 黑旋风沂岭杀四虎-python读写csv和json数据

李逵答应了宋江三件事:不可吃酒,独自前行,不带板斧。李逵痛快答应了,挎一口腰刀,提着朴刀,带了一锭大银子,三五个小银子就下山去了。 宋江放心不下,于是请同乡朱贵也回家一趟&#…

高刷电竞显示器 - HKC VG253KM

今天给大家分享一款高刷电竞显示器 - HKC VG253KM。 高刷电竞显示器 - HKC VG253KM源于雄鹰展翅翱翔的设计灵感,严格遵循黄金分割比例的蓝色点晴线条,加上雾面工艺及高低起伏错落有致的线条处理,在VG253KM的背部勾勒出宛若大鹏展翅的鹰翼图腾…

C习题001:顺子日期【仅供参考】

题目:小明特别喜欢顺子。顺子指的是连续的三个数字:123、456等。顺子日期指的就是在日期的yyyymmdd表示法中,存在任意连续的三位数是一个顺子的日期。例如20220123就是一个顺子日期,因为它出现了一个顺子:123&#xff…

Vue3 (unplugin-auto-import自动导入的使用)

安装 参考链接 npm i -D unplugin-auto-importvite.config.ts里面配置 import AutoImport from unplugin-auto-import/viteAutoImport({imports:[ vue,vue-router]})重新运行项目会生成一个auto-imports.d.ts的文件 /* eslint-disable */ /* prettier-ignore */ // ts-nochec…

springboot项目打成含crud操作的sdk集成到springboot启动引擎项目

一 sdk配置操作 1.1 结构 sdk项目目录中只有基础的service类以及mybatis操作数据库的相关文件,service类中包含查询数据库的方法。 说明: 1.2 sdk的pom打包配置 作为公共项目打成jar供其他项目引用,注意被引入的项目不能使用默认的maven…

Vue3中的select 的option是多余的?

背景&#xff1a; 通过Vue3中填充一个下拉框&#xff0c;在打开页面时要指定默认选中&#xff0c;并在选项改变时把下拉框的选中值显示出来 问题&#xff1a; 填充通常的作法是设置 <option v-for"option in cities" :value"option.value" >&a…

第四套CCF信息学奥赛c++ CSP-J认证初级组 中小学信奥赛入门组初赛考前模拟冲刺题(阅读程序题)

第四套中小学信息学奥赛CSP-J考前冲刺题 二、阅读程序题 (程序输入不超过数组或字符串定义的范围&#xff0c;判断题正确填√错误填X;除特殊说明外&#xff0c;判断题 1.5分&#xff0c;选择题3分&#xff0c;共计40分) 第一题 归并排序 1 #include <iostream> 2 usi…

抖音作品评论id提取工具|视频内容提取软件

抖音视频提取便捷高效&#xff0c;抖音作品评论id提取工具助您快速获取数据 针对抖音作品评论id提取的需求&#xff0c;我们推出了一款功能强大的工具&#xff0c;旨在帮助用户快速提取抖音作品的评论id。无论您是进行数据分析、社交媒体研究还是其他用途&#xff0c;我们的工…
推荐文章