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
典型应用场景
-
生产者-消费者模型:
lualocal 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
-
状态机 :
将复杂状态逻辑拆解为多个
yield
阶段,简化代码结构。 -
协作式任务调度 :
在单线程中模拟多任务并发,如游戏中的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