> 技术文档 > Lua协同程序(coroutine)

Lua协同程序(coroutine)


Lua 协同程序基础概念

Lua 协同程序(coroutine)是一种用户态轻量级线程,允许在单个线程中实现协作式多任务。与操作系统线程不同,协同程序由开发者显式控制切换,不涉及系统调度开销。

  • 特点
    • 非抢占式:需手动调用 yieldresume 切换执行权。
    • 低开销:创建和切换成本远低于系统线程。
    • 共享状态:所有协同程序共享相同 Lua 状态,无需考虑竞态条件。

创建与启动协同程序

通过 coroutine.createcoroutine.wrap 创建,区别在于错误处理和返回值:

-- 方式1:create返回线程对象,需配合coroutine.resume启动local co = coroutine.create(function() print(\"协同程序执行\")end)coroutine.resume(co)-- 方式2:wrap返回可直接调用的函数local f = coroutine.wrap(function() print(\"协同程序执行\")end)f()

控制执行流程

协同程序通过 yield 暂停执行,通过 resume 恢复执行:

local co = coroutine.create(function() for i = 1, 3 do print(\"Yield\", i) coroutine.yield() endend)coroutine.resume(co) -- 输出 Yield 1coroutine.resume(co) -- 输出 Yield 2coroutine.resume(co) -- 输出 Yield 3

数据交换

yieldresume 可双向传递数据:

local co = coroutine.create(function(a) print(\"接收参数:\", a) local b = coroutine.yield(\"第一次yield返回\") print(\"恢复后接收:\", b) return \"结束\"end)local _, msg1 = coroutine.resume(co, \"初始参数\") -- 输出:接收参数: 初始参数print(msg1) -- 输出:第一次yield返回local _, msg2 = coroutine.resume(co, \"新参数\") -- 输出:恢复后接收: 新参数print(msg2) -- 输出:结束

状态查询

通过 coroutine.status 检查协同程序状态:

  • running:当前正在运行的协程。
  • suspended:已暂停或未启动。
  • dead:执行完毕或出错终止。
print(coroutine.status(co)) -- 输出 dead

典型应用场景

  1. 生产者-消费者模型

    local producer = coroutine.create(function() while true do local x = io.read() coroutine.yield(x) endend)local consumer = function() while true do local _, value = coroutine.resume(producer) print(\"消费:\", value) endend
  2. 状态机
    将复杂状态逻辑拆解为多个 yield 阶段,简化代码结构。

  3. 协作式任务调度
    在单线程中模拟多任务并发,如游戏中的NPC行为控制。

注意事项

  • 避免无限循环未 yield,会导致程序阻塞。
  • resume 调用可能引发错误,需用 pcall 包裹处理。
  • 协同程序不适用于CPU密集型并行计算,适合I/O密集型任务。

附:完整生命周期示例

local co = coroutine.create(function() coroutine.yield(\"暂停\") return \"完成\"end)print(coroutine.resume(co)) -- true, \"暂停\"print(coroutine.resume(co)) -- true, \"完成\"print(coroutine.status(co)) -- dead