zoukankan      html  css  js  c++  java
  • 快速上手,协程剖析

    协程也叫微线程,英文名称为coroutine。一个进程可以有多个线程,一个线程可以有多个协程,这是协程和线程间的关系。不同的是,线程由系统调度,但协程需要自己调度,协程运行在用户态。

    Linux内核为协程编程提供了支持,相关的函数声明在ucontext.h头文件中。也可以借助longjmpsetjmp、pthread_attr_setstackaddr等组合实现,但复杂很多,ucontext提供的函数已帮助做了很多工作。要实现协程的并发(线程内的,显然是假并发,实际还是串行的),要求主动调用swapcontext进行切换。

    协程编程实际就是用户态调度函数的执行次数,让单个线程,看起来像是多线程。基于它可以实现伪同步,也就是将异步变成同步调用。

    协程的原理非常简单,假设任务A划分成A1A2A3三个子任务,任务B划分成任务B1B2两个子任务。利用协程,让AB可以并行进行,比如完成A1后,立即执行B1B1完成后执行A2A2完成后执行B2B2完成后执行A3

    为达到这个目的,在执行A1时,A1结束前需要调用swapcontext切换到B1。同理B1完成时,也需要调用swapcontext切换到A2。下面这个示例可以直接编译执行,通过它可以体会到协程的效果。

    // 协程示例

    // 编译g++ -g -o x x.cpp

    #include <stdio.h>

    #include <ucontext.h> // 协程相关api所在头文件

    #include <list>

    // 定义3个协程,类似于3个线程

    static void foo();

    static void woo();

    static void zoo();

    static ucontext_t ctx1; // 协程zoo的上下文,由makecontext调用构造

    static ucontext_t ctx2; // 协程woo的上下文,由makecontext调用构造

    static ucontext_t ctx3; // 协程foo的上下文,由swapcontext自动构造

    // stacknew/malloc出来的也可以的

    static char stack1[4096]; // 协程zoo的栈,得合适大小,否则一样会出现栈溢出

    static char stack2[8192]; // 协程woo的栈,得合适大小,否则一样会出现栈溢出

    int main()

    {

    printf("main 1 ");

        // 构造协程zoo的上下文

    getcontext(&ctx1);

    ctx1.uc_stack.ss_sp = stack1;

    ctx1.uc_stack.ss_size = sizeof(stack1);

    ctx1.uc_link = &ctx3; // ctx1之后的上下文

    makecontext(&ctx1, zoo, 0); // 在运行完zoo之后,运行ctx3

        // 构造协程woo的上下文

    getcontext(&ctx2);

    ctx2.uc_stack.ss_sp = stack2;

    ctx2.uc_stack.ss_size = sizeof(stack2);

    ctx2.uc_link = &ctx1;

    makecontext(&ctx2, woo, 0); // 在运行完zoo之后,运行ctx1

    foo();

    printf("main 2 ");

    return 0;

    }

    // 可把foo当成一个线程,不过它是微线程

    void foo()

    {

    printf("%s 1 ", __func__);

        

        // 切换到ctx2执行,也就是执行woo,当前的保存在ctx3

    swapcontext(&ctx3, &ctx2);

        

        // 当切回到ctx3时,会执行以下代码段

    printf("%s 2 ", __func__);

    }

    // 也可把woo当成一个线程,不过它是微线程

    void woo()

    {

    printf("%s ", __func__);

    }

    // 也可把zoo当成一个线程,不过它是微线程

    void zoo()

    {

    printf("%s ", __func__);

    }

  • 相关阅读:
    nginx article
    学习历程
    GRPC
    学习记录
    JAVA知识点记录
    flag
    读的文章
    This usually happens because your environment has changed since running `npm install`.
    expandedRowKeys、expandedRowsChange、expand
    服务端高并发分布式架构演进之路
  • 原文地址:https://www.cnblogs.com/aquester/p/9891590.html
Copyright © 2011-2022 走看看