一文彻底搞懂协程(coroutine)是什么
创作时间:
作者:
@小白创作中心
一文彻底搞懂协程(coroutine)是什么
引用
1
来源
1.
https://www.cnblogs.com/java-six/p/18438384
协程是一种轻量级的执行单元,它允许程序员在单个线程中实现任务的切换和并发执行。本文将从协程的基本概念出发,通过代码示例展示协程的工作原理,并详细比较协程、线程和进程之间的关系和特点,帮助读者全面理解协程这一重要的编程概念。
什么是协程
总结:程序员可以控制的,类似用户级线程
我们可以简单的认为:协程就是用户态的线程,但是上下文切换的时机是靠调用方(写代码的开发人员)自身去控制的。
同时,协程和用户态线程非常接近,用户态线程之间的切换不需要陷入内核,但部分操作系统中用户态线程的切换需要内核态线程的辅助。
下面是一个简单的例子:
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;
协程、线程和进程之间的关系
协程、线程、进程之间的关系和比较
特性 | 进程 | 线程 | 协程 |
|---|---|---|---|
执行单位 | 独立的执行单元 | 进程内的执行单元 | 线程内的执行单元 |
内存空间 | 独立内存空间 | 共享进程内存空间 | 共享线程内存空间 |
切换开销 | 高 | 较低 | 最低 |
通信方式 | IPC(进程间通信) | 共享内存 | 共享内存、共享状态 |
调度方式 | 由操作系统内核调度 | 由操作系统内核调度 | 由用户程序自行调度 |
并发/并行性 | 并发和并行 | 并发和并行 | 并发(单线程),多线程可并行 |
应用场景 | 独立程序、服务器进程等 | 多任务处理、并发编程 | IO 密集型任务、异步编程 |
协程、线程、进程的关系总结
- 进程包含线程: 一个进程可以包含多个线程,线程是进程的组成部分,多个线程共享进程的资源。
- 线程包含协程: 一个线程可以包含多个协程,协程是在用户态实现的轻量级线程,可以在单个线程内部实现多任务切换。
- 协程与线程、进程的区别: 协程与线程、进程最大的区别在于调度方式。进程和线程由操作系统调度,协程由用户程序自行调度,切换更加高效。
适用场景
- 进程: 适用于需要高隔离度、稳定性较高的场景,比如独立服务、数据库等。
- 线程: 适用于计算密集型任务、多任务并发执行、利用多核 CPU 的场景,比如 Web 服务器、数据处理等。
- 协程: 适用于 IO 密集型任务、异步编程、轻量级多任务切换的场景,比如网络爬虫、异步框架等。
热门推荐
车子的出险维保记录怎么查询?教你三招,挖透二手车的隐藏档案!
朝鲜国宴变迁史:从量大管饱到中西合璧
深圳四个免费赏樱胜地,各具特色等你来
樱花花期及其影响因素(花期长短与气候、品种等因素相关)
Pix2Pix:图像到图像转换的条件生成对抗网络深度解析
汽车保险计算中如何考虑车辆的使用性质
植物神经功能紊乱导致肩膀疼痛如何治疗
MIND饮食:能预防老年痴呆和帕金森病?
如何判断买房还款能力?这几个要点不能忽视
上海十大赏樱花的地方推荐
外出旅游 半数受访者会“打卡”当地的沉浸式体验项目
人形机器人产业爆发,化工新材料是核心
我国招投标领域全面推行保函制度,提升招投标透明度与信任
银行储蓄卡的年费可以取消吗?
朱元璋的政治权术:一个计谋与军事才能不出众之人,却能笑傲群雄
炼油化工催化剂产业将迎来发展新机遇
单倍行距是1.0还是1.5?解释常见的行距设置
湖人完败雄鹿!谁是输球罪魁祸首 ,数据说明一切,不是东契奇
人事工作中的薪酬内容如何与员工福利结合?
薪酬市场专员的招聘信息中薪资待遇怎么样?
深圳跨境电商巨头陨落:有棵树如何从50亿年收入走向负债深渊?
游泳耳塞有用吗?游泳耳塞的作用与适用人群
稳定餐后血糖的饮食小窍门
钻石的等级分别是什么,钻石的等级划分和价格表2025年
解读万有引力的由来,从牛顿到爱因斯坦一步步接近引力的本质!
业务员和销售员的区别
武则天推行告密制度:其背后的动机与对告密者的复杂态度
无纺布的循环利用与再生技术
私人财富管理师|一文读懂保险金信托的功能与优势
树形DP讲解