Lua协同程序(coroutine)

Lua 协同程序基础概念

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

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

创建与启动协同程序

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

lua 复制代码
-- 方式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 恢复执行:

lua 复制代码
local co = coroutine.create(function()
    for i = 1, 3 do
        print("Yield", i)
        coroutine.yield()
    end
end)

coroutine.resume(co) -- 输出 Yield 1
coroutine.resume(co) -- 输出 Yield 2
coroutine.resume(co) -- 输出 Yield 3

数据交换

yield 和 resume 可双向传递数据:

lua 复制代码
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:执行完毕或出错终止。
lua 复制代码
print(coroutine.status(co)) -- 输出 dead

典型应用场景

  1. 生产者-消费者模型:

    lua 复制代码
    local producer = coroutine.create(function()
        while true do
            local x = io.read()
            coroutine.yield(x)
        end
    end)
    
    local consumer = function()
        while true do
            local _, value = coroutine.resume(producer)
            print("消费:", value)
        end
    end
  2. 状态机 :

    将复杂状态逻辑拆解为多个 yield 阶段,简化代码结构。

  3. 协作式任务调度 :

    在单线程中模拟多任务并发,如游戏中的NPC行为控制。

注意事项

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

附:完整生命周期示例

lua 复制代码
local co = coroutine.create(function()
    coroutine.yield("暂停")
    return "完成"
end)

print(coroutine.resume(co)) -- true, "暂停"
print(coroutine.resume(co)) -- true, "完成"
print(coroutine.status(co)) -- dead
相关推荐
努力努力再努力wz16 小时前
【Lua入门系列】从 Table 到元表与元方法:一文理解 Lua 的行为扩展机制
开发语言·junit·lua
麻瓜code2 天前
秒杀优化三连:Lua + 阻塞队列 + Redis Stream,响应从 3.4 秒到毫秒级
redis·junit·lua
努力努力再努力wz2 天前
【Lua 入门系列】Lua 函数深入理解:函数对象、多返回值、可变参数、闭包、递归与尾调用优化
开发语言·lua
hey you~2 天前
云呼叫中心坐席自动分配实战:ACD 策略、Redis+Lua 实现与排查清单
数据库·redis·lua·云呼叫中心·acd·坐席分配·坐席状态机
我不会起名字3222 天前
Redis pipeline 用了反而更慢:3 类误用与正确的批量姿势
redis·pipeline·lua·rtt·批量
努力努力再努力wz3 天前
【Lua入门系列】从 C++ 迭代器到 Lua 迭代器:一文深入理解 Lua 有状态以及无状态迭代器与泛型for、闭包、ipairs、pairs 和 next
开发语言·c++·lua
屈冠成4 天前
ShopXO商城系统测试报告
开发语言·spring·maven·lua
Wang's Blog4 天前
Java 项目实战: 交友项目 - 用户体系集成:根据环信id查询用户详情
java·lua·交友
努力努力再努力wz4 天前
【Lua 入门系列】从顺序执行到分支与循环:一文理解 Lua 控制结构、作用域与跳转规则
junit·单元测试·lua
huoyueyi4 天前
《融天AI-APP从0到1开发实录》
开发语言·lua