c++怎么使用Fiber实现轻量级并发_c++协程式任务切换与用户态调度

Windows原生支持Fiber,Linux可通过ucontext实现用户态协作式多任务调度,提升单线程并发效率。

在C++中使用Fiber(纤程)实现轻量级并发,本质上是通过用户态的协作式多任务调度来提升程序效率。Fiber允许你在单个线程内手动控制执行流的切换,避免操作系统线程切换的开销。Windows平台原生支持Fiber,而Linux可通过模拟类似行为。

理解Fiber与线程的区别

Fiber运行在用户态,由程序员主动调度,不依赖内核调度器。每个线程只能同时执行一个Fiber,但可拥有多个Fiber并手动切换上下文。

  • 线程由操作系统调度,抢占式,开销大
  • Fiber由用户代码调度,协作式,切换快
  • Fiber适合高并发I/O或大量短任务场景

Windows平台下的Fiber使用方法

Windows提供了ConvertThreadToFiber、CreateFiber和SwitchToFiber等API。

1. 将当前线程转为Fiber主上下文:

void* mainFiber = ConvertThreadToFiber(nullptr);

2. 创建新Fiber:

void FiberFunc(void* param) {
    printf("Running in fiber\n");
    SwitchToFiber(mainFiber); // 切回主线程上下文
}

void* fiber = CreateFiber(0, FiberFunc, nullptr);

3. 切换执行流:

SwitchToFiber(fiber); // 跳转到fiber执行
// 控制权交还后继续执行后续代码

4. 清理资源:

DeleteFiber(fiber);
ConvertFiberToThread(); // 可选

跨平台模拟:使用ucontext(Linux/Unix)

Linux没有原生Fiber支持,但可用中的getcontext / setcontext / swapcontext / makecontext模拟。

示例代码片段:

#include 

ucontext_t ctx_main, ctx_fiber; char fiber_stack[8192];

void fiber_func() { printf("In fiber\n"); swapcontext(&ctx_fiber, &ctx_main); // 切回主上下文 }

// 初始化 getcontext(&ctx_fiber); ctx_fiber.uc_stack.ss_sp = fiber_stack; ctx_fiber.uc_stack.ss_size = sizeof(fiber_stack); ctx_fiber.uc_link = &ctx_main; makecontext(&ctx_fiber, fiber_func, 0);

// 切入fiber swapcontext(&ctx_main, &ctx_fiber);

构建简单的协程调度器

可以封装Fiber或ucontext为Task类,并用队列管理待执行任务。

基本思路:

  • 定义Task结构体,保存上下文和状态
  • 维护就绪队列,每次从队列取任务执行
  • 任务主动yield时,保存上下文并重新入队
  • 遇到阻塞操作时切换,提高CPU利用率

简单调度逻辑:

std::queue ready_queue;

void yield() { // 当前任务放回队尾 ready_queue.push(current_task); // 切换到下一个任务 swapcontext(¤t->ctx, &next->ctx); }

这种模型适用于网络服务器、游戏逻辑更新等需大量并发但非计算密集的场景。

基本上就这些。Fiber的核心价值在于减少上下文切换成本,配合事件循环能实现高效的单线程并发。注意它不是万能替代线程的方案——阻塞系统调用会卡住整个线程上的所有Fiber。合理使用,才能发挥其优势。