浅谈协程

引言

基础知识

如果了解一些操作系统的相关知识的话,我们应该知道:进程是资源分配的最小单位,线程是CPU调度的最小单位。

(这里的CPU,指的是一个CPU逻辑核。因为一台主机可能有多个CPU,一个CPU可能有多个核心,CPU可能还支持超线程。)

从进程和线程的角度而言,后台服务程序可以有四种模型: 单进程单线程模型,单进程多线程模型,多进程单线程模型,多进程多线程模型。

通常,一个传统的后台服务程序采用多进程多线程模型(至于为什么,不在本文讨论范围)。有少数几个进程,其中可能有一个master进程用来管理整个程序,一个proxy进程用来代理转发报文给其他进程,然后有一个worker进程来处理实际业务。worker进程通常是多线程的。

传统模型的缺陷

传统的多线程模型存在以下不足:

  1. 线程锁:由于进程才是资源分配的基本单位,不同线程会产生资源竞争的场景,因此需要通过线程锁来保证线程安全。锁的使用需要及其小心。
  2. 同步:不同的线程经常存在需要同步结果的场景。这可能需要借助semaphore、event、join等工具,而且可能还需要有一个线程阻塞来处理其它线程的同步结果。
  3. 性能: 多线程会产生CPU调度,CPU调度是有开销的。

简单的说就是,多线程模型在性能上不够优,而且实现的时候会有很多额外的工作量。

协程在一定程度上解决的这些问题,它基本可以实现多线程模型的效果,又不需要考虑锁、同步等问题。

协程

协程是什么

协程是一种用户态的轻量级线程,协程的调度完全由用户控制。协程拥有自己的寄存器上下文和栈。协程调度切换时,将寄存器上下文和栈保存到其他地方,在切回来的时候,恢复先前保存的寄存器上下文和栈,直接操作栈则基本没有内核切换的开销,可以不加锁的访问全局变量,所以上下文的切换非常快。

以下是来自wikepedia的介绍:

Coroutines are computer-program components that generalize subroutines for non-preemptive multitasking, by allowing multiple entry points for suspending and resuming execution at certain locations. 协同程序是计算机程序组件,它通过允许多个入口点在某些位置暂停和恢复执行来概括用于非抢占式多任务的子程序。

协程的实现原理

在协程中,一个线程里会有多个子程序(任务),这些子程序可以协同合作,看起来就像多个线程一样。然而,我们说线程才是CPU调度的基本单位,不进行CPU到底如何实现多任务呢,前面已经说过,是通过设置一些暂定和恢复子程序执行的入口点实现的。

协程拥有自己的寄存器上下文和栈,协程中的子程序有点类似于函数调用。但是函数调用只有一个入口,且退出后下次调用就需要从头开始执行。而协程允许在子程序的中间多个位置暂定和恢复执行。

下面利用C中的goto,实现一个简单的协程模型:

#include <stdio.h>                                                                               
 
int main()
{
    int line;
    
    {   // 子程序1
        for (int i=0; i < 10; i++) {
            goto coroutine2;
coroutine1:
            printf("coroutine 1: %d\n", i); 
        }
    }   
 
    {   //子程序2
        for (int j=0; j < 10; j++) {
            goto coroutine1; 
coroutine2:
            printf("coroutine 2: %d\n", j); 
        }
    }   
 
    return 0;
}
​

子程序1和子程序2可以像线程那样交替执行,由于两个子程序在同一个函数中,变量i和j的栈空间没有被销毁,而不需保存上下文。

也可以通过setjmp和longjmp来实现用单独函数表示子程序的协程模型。

以上只是通过模型来简单介绍协程的原理,实际应用中可能是通过汇编或其他更精妙的方式来实现协程。

原创声明,本文系作者授权云+社区发表,未经许可,不得转载。

如有侵权,请联系 yunjia_community@tencent.com 删除。

编辑于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏用户2442861的专栏

win64 IDEA meaven 配置安装Thrift自动生成代码到目录

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/haluoluo211/article/details...

5551
来自专栏Python小屋

Python批量Excel文件数据导入SQLite数据库的优化方案

说明:1)需要安装扩展库openpyxl;2)随着数据库的增大,导入速度可能会有所下降;3)本文只考虑Python代码优化,没有涉及数据库的优化;4)本文要点在...

4607
来自专栏我有一个梦想

Python 项目实践三(Web应用程序)第一篇

一 Djangao入门 当今的网站实际上都是富应用程序(rich application),就像成熟的桌面应用程序一样。Python提供了一组开发Web应用程序...

3736
来自专栏Danny的专栏

iterm通过代理访问网络

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/huyuyang6688/article/...

741
来自专栏撸码那些事

使用缓存的正确姿势

缓存是现在系统中必不可少的模块,并且已经成为了高并发高性能架构的一个关键组件。这篇博客我们来分析一下使用缓存的正确姿势。

5046
来自专栏跟着阿笨一起玩NET

WSDL手动生成WebService代理类的方法

通常要手动生成WebService代理类需要把一句生成语句,如 wsdl.exe /l:cs /out:D:\Proxy_UpdateService.cs ht...

4081
来自专栏CreateAMind

ls-gan bedroom数据集 pretrain model 和代码

pretrain model 和代码 https://pan.baidu.com/s/1dFbzjlZ pretrain 下载

1122
来自专栏C/C++基础

Linux命令(28)——tee命令

tee命令从标准输入读取数据后,将数据重定向到给定的文件和标准输出。给定的文件可以有多个。

1271
来自专栏计算机视觉

Automatic Photo Adjustment Using Deep Neural Networks 论文实验训练测试部分

安装双系统ubuntu和cuda和 dl_image_enhance安装部分教程,这个小哥哥写的很好 我写下安装cuda_convent_plus和训练测试...

34710
来自专栏互联网杂技

利用机器学习把草图自动生成HTML

项目地址 https://github.com/ashnkumar/sketch-code 可以先clone到本地

1622

扫码关注云+社区

领取腾讯云代金券