协程,以C和C#为例
一、协程的核心概念
协程(Coroutine)是一种用户态的轻量级并发模型,允许在单线程中通过协作式调度实现多个任务的交替执行。其核心特性包括:
- 非抢占式切换:协程主动让出执行权,而非被系统强制中断。
- 状态保存与恢复:每次挂起时保存局部变量和执行位置,恢复时从断点继续。
- 低开销:上下文切换仅需修改寄存器,无需内核介入,性能比线程高10-100倍。
- 适用场景:I/O密集型任务(如网络服务器)、游戏逻辑、状态机实现。
- 非阻塞:在单线程中模拟并发,避免线程切换开销。
- 灵活控制:开发者可手动定义暂停条件(如等待时间、帧间隔等)。
二、C语言实现协程的常见方法
1. 基于libco库的实现
特点:高性能协程库(微信开源),底层使用汇编保存寄存器状态,支持百万级协程并发。
#include <stdio.h>
#include "co.h"
void coroutine_a() {
printf("协程A启动\n");
co_yield(); // 主动让出CPU
printf("协程A恢复\n");
}
void coroutine_b() {
printf("协程B启动\n");
co_yield();
printf("协程B恢复\n");
}
int main() {
stCoRoutine_t *co_a, *co_b;
co_create(&co_a, NULL, coroutine_a); // 创建协程
co_create(&co_b, NULL, coroutine_b);
co_resume(co_a); // 启动协程A
co_resume(co_b); // 启动协程B
// 再次恢复协程以执行后续代码
co_resume(co_a);
co_resume(co_b);
co_eventloop(co_get_epoll_ct()); // 事件循环
return 0;
}
编译命令:gcc -o demo demo.c -lco
输出结果:
协程A启动
协程B启动
协程A恢复
协程B恢复
2.基于setjmp/longjmp的轻量级实现
特点:无需外部库,但无法自动保存栈数据(需手动管理)
#include <setjmp.h>
#include <stdio.h>
jmp_buf main_env, co_env;
void coroutine() {
printf("协程启动\n");
if (!setjmp(co_env))
longjmp(main_env, 1); // 切换回主函数
printf("协程恢复\n");
}
int main() {
if (!setjmp(main_env)) {
coroutine();
} else {
printf主函数恢复\n");
longjmp(co_env, 1); // 再次切换至协程
}
return 0;
}
三、C#协程的两种实现方式
1.基于迭代器(IEnumerator)的协程
适用场景:游戏开发(如Unity)、逐帧操作或需要精细控制执行流程的场景。
实现原理:使用yield return关键字定义暂停点,编译器自动生成状态机类。通过IEnumerator接口管理协程生命周期(如MoveNext()方法)
using System.Collections;
using UnityEngine;
public class CoroutineDemo : MonoBehaviour {
void Start() {
StartCoroutine(MyCoroutine());
}
IEnumerator MyCoroutine() {
Debug.Log("协程开始");
yield return new WaitForSeconds(1); // 暂停1秒[1,6](@ref)
Debug.Log("1秒后继续执行");
yield return null; // 等待下一帧[3](@ref)
Debug.Log("下一帧执行");
}
}

浙公网安备 33010602011771号