文章目录

Lua 协程:coroutine.create() 与 resume()

发布于 2026-04-02 09:00:21 · 浏览 8 次 · 评论 0 条

Lua 协程:coroutine.create()resume()

Lua 的协程(coroutine)是一种轻量级的协作式多任务机制。它允许你将一段代码暂停执行,并在之后从暂停处继续运行,而无需依赖操作系统线程。要启动一个协程,核心操作就是 创建恢复——分别通过 coroutine.create()coroutine.resume() 实现。


创建协程:coroutine.create()

调用 coroutine.create() 并传入一个函数,即可生成一个新的协程对象。

  1. 定义 一个普通的 Lua 函数,该函数将作为协程的执行体。例如:

    function my_task()
        print("协程开始")
        coroutine.yield()  -- 暂停协程
        print("协程继续")
    end
  2. 调用 coroutine.create(my_task) 创建协程:

    co = coroutine.create(my_task)

    此时 co 是一个类型为 "thread" 的协程对象,但尚未执行任何代码。

  3. 检查 协程状态(可选):

    print(coroutine.status(co))  -- 输出 "suspended"

    新创建的协程处于 "suspended" 状态,表示已准备好但未运行。

注意:coroutine.create() 不会立即执行函数内容,只是“打包”好待运行的代码。


启动或恢复协程:coroutine.resume()

调用 coroutine.resume() 才真正开始执行协程,或从中断处继续。

  1. 首次调用 coroutine.resume(co) 启动协程:

    success, result = coroutine.resume(co)
    • 此时会执行 my_task() 中的第一行 print("协程开始")
    • 遇到 coroutine.yield() 后暂停。
    • successtrue(表示无错误),resultnil(因为 yield() 未传值)。
  2. 再次调用 coroutine.resume(co) 恢复执行:

    success, result = coroutine.resume(co)
    • 协程从 yield() 下一行继续,输出 "协程继续"
    • 函数执行完毕,协程进入 "dead" 状态。
  3. 传递参数 给协程(首次 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)
  4. 向已暂停的协程传递数据(后续 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"(结束)

常见误区与注意事项

  1. 不要对已死亡的协程调用 resume()
    若协程已执行完毕(状态为 "dead"),再次调用 coroutine.resume() 会返回 false 和错误信息:

    co = coroutine.create(function() end)
    coroutine.resume(co)  -- 成功,状态变 "dead"
    coroutine.resume(co)  -- 失败:cannot resume dead coroutine
  2. create() 不等于 wrap()
    coroutine.wrap() 也创建协程,但返回的是一个函数,调用它等价于 resume(),且直接抛出错误而非返回 false。本文聚焦于 create() + resume() 的显式控制模式。

  3. 协程不是并行
    Lua 协程是协作式的:只有主动调用 yield() 才会让出控制权。同一时间只有一个协程在运行。

  4. 嵌套协程需谨慎
    在协程 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() 传递数据的完整协作流程。

评论 (0)

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

扫一扫,手机查看

扫描上方二维码,在手机上查看本文