版本比较

标识

  • 该行被添加。
  • 该行被删除。
  • 格式已经改变。

...

Graphviz
UUIDgraphviz_container_use_caller_false
digraph {
    rankdir=LR;
    node [style=filled];
    compound=true;

    subgraph sub1 {
        start [label="main函数开始" shape=none style=""];
        main1 [label = "创建调度器"];
        main2 [label = "开始调度"];
        main3 [label = "添加调度任务"];
        main4 [label = <停止调度<BR/>(等待调度线程退出)>];
        end [label="main函数结束" shape=none style=""];
        rank=same;
        start -> main1 -> main2 -> main3 -> main4 -> end;
    }
    subgraph sbu2 {
        scheduler1 [label="调度协程" style=filled];
        scheduler2 [label="调度协程" style=filled];
        scheduler3 [label="调度协程" style=filled];
        scheduler4 [label="调度协程" style=filled]
        scheduler_end [label="结束调度线程结束"]
        child1 [label="子协程1"]
        child2 [label="子协程2"]
        child3 [label="子协程3"]
        
        {rank=same; scheduler1 scheduler2 scheduler3 scheduler4 scheduler_end}
        {rank=same; child1 child2 child3}
    }
    scheduler1->child1->scheduler2->child2->scheduler3->child3->scheduler4->scheduler_end;
    main2->scheduler1[label="创建调度线程"];
}

...

Graphviz
UUIDgraphviz_container_use_caller_true
digraph {
    rankdir=LR;
    node [style=filled];
    compound=true;

    subgraph sub1 {
        start [label="main函数开始" shape=none style=""];
        main1 [label = "创建调度器"];
        main2 [label = <开始调度<BR/>(实际什么也没做)>];
        main3 [label = "添加调度任务"];
        main4 [label = <停止调度<BR/>>];
        end [label="main函数结束" shape=none style=""];
        rank=same;
        start -> main1 -> main2 -> main3 -> main4 -> end;
    }
    subgraph sbu2 {
        scheduler1 [label="调度协程" style=filled];
        scheduler2 [label="调度协程" style=filled];
        scheduler3 [label="调度协程" style=filled];
        scheduler4 [label="调度协程" style=filled]
        child1 [label="子协程1"]
        child2 [label="子协程2"]
        child3 [label="子协程3"]

        {rank=same; scheduler1 scheduler2 scheduler3 scheduler4}
        {rank=same; child1 child2 child3}
    }
    scheduler1->child1->scheduler2->child2->scheduler3->child3->scheduler4;
    main4 -> scheduler1 [label="切到调度协程"];
    scheduler4 -> main4 [label=<全部任务执行结束后<BR/>调度协程返回main函数主协程>];
}


然而,回顾一下前面协程模块就会发现,上面这种协程切换实际是有问题的,参考下面这张图:

Graphviz
UUIDgraphviz_container_asm_fiber_bad_bad
digraph asymmetric_fiber {
    rankdir=LR;
    
    start [label="开始" shape=none style=""];
    main1 [label = "主协程" style=filled];
    main2 [label = "主协程" style=filled];
    main3 [label = "主协程" style=filled];
    main4 [label = "主协程" style=filled];
    end [label="结束" shape=none style=""];
    {rank=same; start main1 main2 main3 main4 end;}
    

    sub1 [label="子协程1"];
    sub2 [label="子协程2"];
    sub3 [label="子协程3"];
    sub5 [label="子协程5"];
    {rank=same; sub1 sub2 sub3 sub5;}

    sub4 [label="子协程4"];
    sub6 [label="子协程6"];
    {rank=same; sub4 sub6;}

    start -> main1;
    main1 -> sub1;
    sub1 -> main2;
    main2 -> sub2;
    sub2 -> main3;
    main3 -> sub3;
    sub3 -> sub4;
    sub4 -> sub5;
    sub5 -> sub6;
    sub6 -> main4 [label="无法切回主协程" style=dotted];
    main4 -> end;
}


在非对称协程里,子协程只能和线程主协程切换,而不能和另一个子协程切换。在上面的情况1中,线程主协程是main函数对应的协程,另外的两类协程,也就是调度协程和任务协程,都是子协程,但

sylar协程模块运行图示


然后描述一下协程调度的本质。

...