Lua 协程:coroutine.create() 与 resume()
Lua 的协程(coroutine)是一种轻量级的协作式多任务机制。它允许你将一段代码暂停执行,并在之后从暂停处继续运行,而无需依赖操作系统线程。要启动一个协程,核心操作就是 创建 和 恢复——分别通过 coroutine.create() 和 coroutine.resume() 实现。
创建协程:coroutine.create()
调用 coroutine.create() 并传入一个函数,即可生成一个新的协程对象。
-
定义 一个普通的 Lua 函数,该函数将作为协程的执行体。例如:
function my_task() print("协程开始") coroutine.yield() -- 暂停协程 print("协程继续") end -
调用
coroutine.create(my_task)创建协程:co = coroutine.create(my_task)此时
co是一个类型为"thread"的协程对象,但尚未执行任何代码。 -
检查 协程状态(可选):
print(coroutine.status(co)) -- 输出 "suspended"新创建的协程处于
"suspended"状态,表示已准备好但未运行。
注意:
coroutine.create()不会立即执行函数内容,只是“打包”好待运行的代码。
启动或恢复协程:coroutine.resume()
调用 coroutine.resume() 才真正开始执行协程,或从中断处继续。
-
首次调用
coroutine.resume(co)启动协程:success, result = coroutine.resume(co)- 此时会执行
my_task()中的第一行print("协程开始")。 - 遇到
coroutine.yield()后暂停。 success为true(表示无错误),result为nil(因为yield()未传值)。
- 此时会执行
-
再次调用
coroutine.resume(co)恢复执行:success, result = coroutine.resume(co)- 协程从
yield()下一行继续,输出"协程继续"。 - 函数执行完毕,协程进入
"dead"状态。
- 协程从
-
传递参数 给协程(首次 resume):
function task_with_args(a, b) print("收到参数:", a, b) local sum = coroutine.yield(a + b) print("从外部传回:", sum) end co2 = coroutine.create(task_with_args) success, result = coroutine.resume(co2, 10, 20) -- 传入 10, 20 -- 输出: 收到参数: 10 20 -- result = 30(即 a + b) -
向已暂停的协程传递数据(后续 resume):
success, result = coroutine.resume(co2, 50) -- 输出: 从外部传回: 50 -- result = nil(函数结束无返回值)
coroutine.resume()的第一个返回值是布尔值,表示协程是否成功运行(若协程中出错则为false)。后续返回值来自yield()或函数的最终返回值。
关键行为对比表
| 操作 | 函数签名 | 返回值说明 | 协程状态变化 |
|---|---|---|---|
coroutine.create(f) |
接收一个函数 f |
返回协程对象 co |
"suspended"(初始挂起) |
coroutine.resume(co, ...) |
第一个参数是协程对象,后续是传入值 | 成功时:true, ...(... 来自 yield 或函数返回)<br>失败时:false, 错误信息 |
"suspended" → "running" → "suspended"(遇到 yield)或 "dead"(结束) |
常见误区与注意事项
-
不要对已死亡的协程调用
resume()
若协程已执行完毕(状态为"dead"),再次调用coroutine.resume()会返回false和错误信息:co = coroutine.create(function() end) coroutine.resume(co) -- 成功,状态变 "dead" coroutine.resume(co) -- 失败:cannot resume dead coroutine -
create()不等于wrap()
coroutine.wrap()也创建协程,但返回的是一个函数,调用它等价于resume(),且直接抛出错误而非返回false。本文聚焦于create()+resume()的显式控制模式。 -
协程不是并行
Lua 协程是协作式的:只有主动调用yield()才会让出控制权。同一时间只有一个协程在运行。 -
嵌套协程需谨慎
在协程 A 中启动协程 B 是允许的,但resume(B)必须在 A 的上下文中调用,且 B 结束后控制权回到 A,而非主程序。
完整示例:生产者-消费者模型
以下代码演示如何用两个协程实现简单的生产者-消费者通信:
function producer()
for i = 1, 3 do
print("生产:", i)
coroutine.yield(i) -- 将 i 传给消费者
end
end
function consumer(prod_co)
while true do
local success, value = coroutine.resume(prod_co)
if not success then
print("生产者出错:", value)
break
end
if coroutine.status(prod_co) == "dead" then
print("生产结束")
break
end
print("消费:", value)
end
end
-- 创建生产者协程
prod = coroutine.create(producer)
-- 启动消费者(它会驱动生产者)
consumer(prod)
执行结果:
生产: 1
消费: 1
生产: 2
消费: 2
生产: 3
消费: 3
生产结束
此例清晰展示了 create() 构建协程、resume() 驱动执行、yield() 传递数据的完整协作流程。

暂无评论,快来抢沙发吧!