当前位置: 首页 > news >正文

C++协程和线程的区别?详细介绍一下C++协程

C++协程和线程的区别

  • 线程是操作系统级别的资源,由操作系统负责调度和切换,每个线程都有自己的堆栈和执行上下文。线程之间的切换需要保存和恢复线程的执行上下文,这个过程有一定的开销。
  • 协程是用户态的轻量级线程,协程的调度完全由用户控制,一个线程可以拥有多个协程,协程之间的切换不需要操作系统的干预,因此开销更小。协程也有自己的堆栈和执行上下文,但是协程的堆栈是动态分配的,可以根据需要增长或缩小,协程的执行上下文是保存在协程状态中的,协程状态是分配在堆上的内部对象。
  • 线程是同步机制,即线程在执行过程中如果遇到阻塞,比如IO操作,就会让出CPU,等待阻塞结束后再继续执行。这样会导致线程的资源浪费和调度开销的增加。线程之间如果要共享数据,还需要使用锁机制来避免竞争和冲突,这也会增加复杂度和开销。
  • 协程是异步机制,即协程在执行过程中可以主动挂起,让出CPU,然后在适当的时候再恢复执行。这样可以避免无意义的等待和切换,提高CPU的利用率。协程之间如果要共享数据,不需要使用锁机制,只需要判断状态就可以了,这也会降低复杂度和开销。

C++协程的基本概念和用法

  • C++协程是在C++20标准中引入的一个新特性,目的是为了简化异步编程的模式,提高性能和效率。C++协程的实现主要依赖于三个新的关键字:co_await, co_yield, co_return,以及一些新的类型和库函数。
  • C++协程是一种特殊的函数,它的返回类型必须是一个有promise_type成员类型的类型,比如std::future, std::generator, std::task等。这个promise_type类型是一个承诺对象,它负责生成协程函数的返回对象,提交协程的结果或异常,以及控制协程的启动和终止行为。
  • C++协程可以使用co_await关键字来调用一个等待体对象,根据其内部定义决定其操作是挂起还是继续,以及挂起和恢复时的行为。等待体对象必须有await_ready, await_suspend, await_resume三个成员函数,或者重载了operator co_await的类型。一般而言,等待体对象可以表示一个异步操作,比如网络IO,文件读写,定时器等。
  • C++协程可以使用co_yield关键字来挂起协程,并且产生一个值,这个值会保存在承诺对象中,通过yield_value函数。在协程外部可以通过承诺对象得到这个值。这个机制可以用来实现生成器,即按需产生值的函数。
  • C++协程可以使用co_return关键字来终止协程,并且返回一个值,这个值会保存在承诺对象中,通过return_value函数。在协程外部可以通过承诺对象得到这个值。这个机制可以用来实现异步函数,即返回一个未来值的函数。
  • C++协程的唯一标识是协程句柄,它是一个std::coroutine_handle模板类的实例,它可以用来恢复或销毁协程。协程句柄可以通过承诺对象的get_return_object函数或者from_promise静态函数得到。协程句柄还可以访问协程状态,即保存协程的上下文和数据的对象。

以下是一个简单的C++协程的例子,实现了一个生成斐波那契数列的函数:

#include <iostream>
#include <coroutine>// 定义一个生成器类型,用于返回协程函数的对象
template<typename T>
struct generator {// 定义一个承诺类型,用于控制协程的行为struct promise_type {// 保存协程产生的值T value;// 生成协程函数的返回对象generator get_return_object() {// 从承诺对象中获取协程句柄return generator{ std::coroutine_handle<promise_type>::from_promise(*this) };}// 表示协程启动后不立即挂起std::suspend_never initial_suspend() {return {};}// 表示协程终止后不再恢复std::suspend_never final_suspend() noexcept {return {};}// 处理协程的返回值void return_void() {}// 处理协程的异常void unhandled_exception() {std::terminate();}// 保存协程的产生的值std::suspend_always yield_value(T val) {value = val;return {};}};// 保存协程句柄std::coroutine_handle<promise_type> handle;// 构造函数,从协程句柄初始化explicit generator(std::coroutine_handle<promise_type> h) : handle(h) {}// 析构函数,销毁协程~generator() {if (handle) {handle.destroy();}}// 生成器不能被拷贝,只能被移动generator(const generator&) = delete;generator& operator=(const generator&) = delete;generator(generator&& other) noexcept : handle(other.handle) {other.handle = nullptr;}generator& operator=(generator&& other) noexcept {handle = other.handle;other.handle = nullptr;return *this;}// 返回协程产生的值T value() const {return handle.promise().value;}// 恢复协程的执行void resume() {handle.resume();}// 判断协程是否结束bool done() const {return handle.done();}
};// 定义一个协程函数,返回一个生成器对象,用于生成斐波那契数列
generator<int> fibonacci(int n) {int a = 0, b = 1;for (int i = 0; i < n; i++) {co_yield a; // 挂起协程,并产生一个值auto tmp = a;a = b;b = tmp + b;}
}int main() {// 调用协程函数,得到一个生成器对象auto gen = fibonacci(10);// 循环访问生成器产生的值,直到协程结束while (!gen.done()) {std::cout << gen.value() << " "; // 输出协程产生的值gen.resume(); // 恢复协程的执行}std::cout << std::endl;return 0;
}

输出结果:

0 1 1 2 3 5 8 13 21 34

Cpp中的线程,纤程和协程 - 知乎 (zhihu.com) 

(73 封私信) 如何理解协程和线程,以及它们之间的区别? - 知乎 (zhihu.com) 

相关文章:

C++协程和线程的区别?详细介绍一下C++协程

C协程和线程的区别 线程是操作系统级别的资源&#xff0c;由操作系统负责调度和切换&#xff0c;每个线程都有自己的堆栈和执行上下文。线程之间的切换需要保存和恢复线程的执行上下文&#xff0c;这个过程有一定的开销。协程是用户态的轻量级线程&#xff0c;协程的调度完全由…...

数字信号处理期末复习——计算大题(一)

个人名片&#xff1a; &#x1f981;作者简介&#xff1a;一名喜欢分享和记录学习的在校大学生 &#x1f42f;个人主页&#xff1a;妄北y &#x1f427;个人QQ&#xff1a;2061314755 &#x1f43b;个人邮箱&#xff1a;2061314755qq.com &#x1f989;个人WeChat&#xff1a;V…...

matlab数值计算函数--ode45

当难以求得微分方程的解析解时&#xff0c;可以求其数值解&#xff0c;Matlab中求微分方程数值解的函数有七个&#xff1a;ode45&#xff0c;ode23&#xff0c;ode113&#xff0c;ode15s&#xff0c;ode23s&#xff0c;ode23t&#xff0c;ode23tb。本文讲解ode45&#xff0c;其…...

Vue3地图选点组件

Vue3地图选点组件 <template><div style"width: 100%; height: 500px"><div class"search-container"><el-autocompletev-model"suggestionKeyWord"class"search-container__input"clearable:fetch-suggestion…...

JS之注册事件兼容性解决方案

本章介绍注册事件兼容性的解决方案 废话不多说&#xff0c;直接上代码&#xff1a; function addEventListener(element, eventName, fn) {//判断当前浏览器是否支持 addEventListener 方法if (element.addEventListener) {element.addEventListener(eventName, fn); // 第三个…...

C#中使用as关键字将对象转换为指定类型

目录 一、定义 二、示例 三、生成 使用as关键字可以将对象转换为指定类型&#xff0c;与is关键字不同&#xff0c;is关键字用于检查对象是否与给定类型兼容&#xff0c;如果兼容则返回true&#xff0c;如果不兼容则返回false。而as关键字会直接进行类型转换&#xff0c;如果…...

【Spring实战】21 Spring Data REST 常用功能详细介绍

文章目录 1. 资源导出&#xff08;Resource Exporting&#xff09;2. 查询方法&#xff08;Query Methods&#xff09;3. 分页和排序&#xff08;Pagination and Sorting&#xff09;4. 关联关系&#xff08;Associations&#xff09;5. 事件&#xff08;Events&#xff09;6. …...

05-微服务-RabbitMQ-概述

RabbitMQ 1.初识MQ 1.1.同步和异步通讯 微服务间通讯有同步和异步两种方式&#xff1a; 同步通讯&#xff1a;就像打电话&#xff0c;需要实时响应。 异步通讯&#xff1a;就像发邮件&#xff0c;不需要马上回复。 两种方式各有优劣&#xff0c;打电话可以立即得到响应&am…...

jmeter参数化的三种方式

1.用户定义变量 使用变量&#xff1a; ${变量名} 这个变量是全局变量&#xff0c;也就是在下面子节点中都可以使用&#xff1b; 使用场景&#xff1a;两个账号分别有不同的权限&#xff0c;A经办&#xff0c;B审核。等。。。 2.CSV数据文件设置 3.函数...

java基础之Java8新特性-Lambda

目录 什么是Lambda表达式 Lambda表达式规范 基本语法 参数列表 函数体 注意事项 如何定义函数接口 1.保证接口中只能有一个抽象方法 2.使用FunctionalInterface注解标记该接口为函数接口 使用Lambda调用无参函数 使用Lambda调用有参函数 使用Lambda的精简写法 使用…...

入门使用mybatis-plus

第一步&#xff1a;pom文件带入依赖 <dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.1</version> </dependency> 第二步&#xff1a;创建实体对象 TableName(&…...

ubuntu安装和配置ssh教程

一、前言 ssh服务类似于windows的远程桌面服务,可以实现对linux系统的远程管理,ssh默认端口为22端口。后面博主进行操作以ubuntu2020操作系统为例进行操作。 二、安装ssh服务 Ubuntu 2020 默认不安装 SSH 服务。它只安装了 SSH 客户端,可以用于连接到其他计算机上的 SSH 服…...

每天刷两道题——第六天

1.1字母异位词分组 给你一个字符串数组&#xff0c;将字母异位词组合在一起。可以按任意顺序返回结果列表。字母异位词指的是由重新排列源单词的所有字母得到的一个新单词。 输入: strs [“eat”, “tea”, “tan”, “ate”, “nat”, “bat”] 输出: [[“bat”],[“nat”,…...

时间序列平稳性相关检验方法

理解平稳性 一般来说&#xff0c;平稳时间序列是指随着时间的推移具有相当稳定的统计特性的时间序列&#xff0c;特别是在均值和方差方面。平稳性可能是一个比较模糊的概念&#xff0c;将序列排除为不平稳可能比说序列是平稳的更容易。通常不平稳序列有几个特征&#xff1a; …...

<leetcode修炼>双指针训练-移动零

题目: 给定一个数组 nums&#xff0c;编写一个函数将所有 0 移动到数组的末尾&#xff0c;同时保持非零元素的相对顺序。 请注意 &#xff0c;必须在不复制数组的情况下原地对数组进行操作。 方法1: 快慢指针 快指针负责遍历数组中所有元素&#xff0c;慢指针负责记录不为0的…...

Python初探:从零开始的编程奇妙之旅

一、Python是什么 Python是一门多用途的高级编程语言&#xff0c;以其简洁、易读的语法而脱颖而出。在深度学习领域&#xff0c;Python扮演着至关重要的角色。其丰富的科学计算库&#xff08;如NumPy、Pandas、Matplotlib&#xff09;和强大的深度学习框架&#xff08;如Tenso…...

算法与数据结构之链表<一>(Java)

目录 1、链表的定义 2、链表的特点 3、为何要使用链表 4、数组与链表的区别 5、链表的增删查 5.1、在头部插入链表 5.2、在中间插入链表 5.3、删除头节点 5.4、删除中间节点 5.5、查询某个值 6、链表的应用 6.1 如何设计一个LRU缓存算法&#xff1f; 6.2 约瑟夫问题 1、链表的定…...

目标检测COCO数据集与评价体系mAP

1.mAP 2.IoU IoU也就是交并比&#xff0c;也称为 Jaccard 指数&#xff0c;用于计算真实边界框与预测边界框之间的重叠程度。它是真值框与预测边界框的交集和并集之间的比值。Ground Truth边界框是测试集中手工标记的边界框&#xff0c;用于指定对象图像的位置以及预测的边界框…...

2024最全面且有知识深度的web3开发工具、web3学习项目资源平台

在Web3技术迅速发展的时代&#xff0c;寻找一个综合且深入的Web3开发工具和学习项目资源平台变得至关重要。今天&#xff0c;我将向大家介绍一个非常有价值的网站&#xff0c;它就是https://web3x.world 。 Web3X是一个全面而深入的Web3开发者社区&#xff0c;为开发者们提供了…...

Golang - defer关键字 深入剖析

defer关键字 defer和go一样都是Go语言提供的关键字。defer用于资源的释放&#xff0c;会在函数返回之前进行调用。一般采用如下模式&#xff1a; f,err : os.Open(filename) if err ! nil {panic(err) } defer f.Close()如果有多个defer表达式&#xff0c;调用顺序类似于栈&a…...

如何在Spring Boot中使用@Scheduled写定时任务判断数据量是否过大,过大则进行分表操作,多张表使用临时视图查询

当数据量过大&#xff0c;在定时任务中执行分表操作 1、复制表结构及数据 在xml中编写复制表结构及数据&#xff08;newTableName为新表名、originalTableName为原始表名&#xff09; 只复制表结构&#xff1a; CREATE TABLE ${newTableName} AS SELECT * FROM ${originalTa…...

使用jieba库进行中文分词和去除停用词

jieba.lcut jieba.lcut()和jieba.lcut_for_search()是jieba库中的两个分词函数&#xff0c;它们的功能和参数略有不同。 jieba.lcut()方法接受三个参数&#xff1a;需要分词的字符串&#xff0c;是否使用全模式&#xff08;默认为False&#xff09;以及是否使用HMM模型&…...

C语言之分支与循环【附6个练习】

文章目录 前言一、什么是语句&#xff1f;1.1 表达式语句1.2 函数调用语句1.3 控制语句1.4 复合语句1.5 空语句 二、分支语句&#xff08;选择结构&#xff09;2.1 if语句2.1.1 悬空else2.1.2 练习&#xff08;1. 判断一个数是否为奇数 2. 输出1-100之间的奇数&#xff09; 2.2…...

使用通用MCU实现无人机飞行任务的快速二次开发

使用通用MCU实现无人机飞行任务的快速二次开发 ---TIDronePilot外部控制offboard模式介绍 无名小哥 2024年1月1日 传统飞控二次开发方法和主要存在的问题简介 通过对前面几讲中《零基础竞赛无人机积木式编程指南》系列开发教程的学习可知&#xff0c;在以往TI电赛真题的学习…...

什么是Selinux

官网地址&#xff1a;What is SELinux? 欢迎关注留言&#xff0c;我是收集整理小能手&#xff0c;工具翻译&#xff0c;仅供参考&#xff0c;笔芯笔芯. 概述 安全增强型 Linux (SELinux) 是Linux 系统的安全架构&#xff0c;允许管理员更好地控制谁可以访问系统。它最初是由美…...

计算机网络知识点

1. URI 和 URL 统一资源定位符&#xff08;Uniform Resource Locator&#xff0c;缩写&#xff1a;URL&#xff09;&#xff0c;是对资源的引用和访问该资源的方法。俗称网址&#xff0c;就是浏览器地址栏里面的内容。 URL 语法为&#xff1a;protocol://userInfohost:port/p…...

Qt 连接 Mysql

Linux下安装mysql及qt连接_liunx下安装mysql及qt链接-CSDN博客...

HarmonyOS4.0系统性深入开发14AbilityStage组件容器

AbilityStage组件容器 AbilityStage是一个Module级别的组件容器&#xff0c;应用的HAP在首次加载时会创建一个AbilityStage实例&#xff0c;可以对该Module进行初始化等操作。 AbilityStage与Module一一对应&#xff0c;即一个Module拥有一个AbilityStage。 DevEco Studio默…...

客服系统接入FastGPT

接入FastGPT 点击【应用】【外部使用】【API访问】【新建】新建一个KEY&#xff0c;同时也可以看到我们的API根地址 这个根地址和Key可以填入任何支持OpenAI接口的应用里&#xff0c;这个接口是兼容OpenAI格式。 在客服系统【知识库AI配置】里填上接口地址和接口密钥。这样我…...

Hi5 2.0 虚拟手与追踪器(Tracker)的位置修正

问题描述 使用环境与工具&#xff1a;Unity 2022.3.4fc1&#xff0c;steam VR(2.7.3)&#xff0c;steamvrSDK&#xff08;1.14.15&#xff09;&#xff0c;HTC vive pro专业版&#xff0c;Hi5 2.0数据手套 首先按照Hi5 2.0的使用说明&#xff08;可参考&#xff1a;HI5 2.0 交…...

有人做几个蝎子养殖门户网站/指数函数图像及性质

今天我很烦&#xff0c;昨天网站有问题&#xff0c;上午提交&#xff0c;下午恢复。今天一早又没了&#xff0c;说是没缴费的问题&#xff0c;打了无数客服电话非说是我的域名有问题&#xff0c;哦赛&#xff0c;真麻烦啊。本来想再置办一个&#xff0c;想想真是怕了&#xff0…...

制作网站的公司不干了/营销软件有哪些

其中 if (rs.next()false) {查不到数据 sql执行false rs.next() 如果第一次返回False表示返回为空 如果执行后第一个结果是ResultSet&#xff0c;则返回true&#xff0c;否则返回false。public boolean getAllopenid(int tieziid,String openid6) {//public ArrayList getAll(i…...

syntax highlighter for wordpress/黑帽seo教程

毫无PS痕迹 你的第一本Photoshop书 目录 《毫无PS痕迹-你的本Photoshop书》全书分为四大部分&#xff1a; 第1、2章讲解色彩和图像的原理与基础知识要点。 第3至11章全面讲解了使用Photoshop进行各种设计创作的方法与技巧。这包括色彩调整工具的使用、极其重要的选区、蒙版与图…...

网易邮箱网页版/上海外包seo

这里只写cacti监控lvs的部分&#xff0c;前提是cacti安装完成。服务端&#xff08;下载2个附件&#xff09;1.服务端添加模板cacti_data_query_snmp_lvs.xml2.将 snmp-lvs.xml 拷贝到source 目录下客户端(lvs机器-这里针对5和4的32位系统&#xff0c;el5_64位不适用)A 安装 net…...

手机网站经典案例/什么关键词能搜到资源

量子纠缠是科学家探索的重要方向之一。而实现多原子纠缠&#xff0c;更是材料科学和量子计算领域的科学家和工程师追求的目标。最近&#xff0c;德累斯顿工业大学&#xff08;TUD&#xff09;和慕尼黑工业大学&#xff08;TUM&#xff09;的研究人员发现了一种全新的相变类型&a…...

三站合一 网站建设/深圳关键词优化公司哪家好

玩python的人大都在linux下进行开发,由于长期习惯在windows下开发代码&#xff0c;今天蛋疼尝试在window7下配置python2.7tornado3.3开发环境&#xff0c;必然的中间遇到各种报错&#xff0c;但是最终还是配置成功了&#xff0c;发帖方便网友少走弯路.开工&#xff01; 前提: p…...