016-Lua 协同程序(Coroutine)详解

Lua 的协同程序(coroutine)是轻量级线程(并非操作系统线程),用于实现协作式多任务编程。协同程序允许在函数执行过程中暂停(yield)和恢复(resume),从而灵活地控制程序的执行流。


1. 协同程序的基本概念

  • 协同程序是 Lua 中的一种线程。
  • 它与传统的多线程不同,协同程序是协作式的,即由程序显式地交出(yield)和恢复(resume)控制权。
  • 协同程序通过 coroutine 库提供的 API 来操作。

1.1 协同程序的生命周期

协同程序的状态可以是以下几种:

  1. suspended:初始状态,或在调用 coroutine.yield() 后暂停。
  2. running:正在运行中。
  3. normal:正在 resume 另一个协同程序。
  4. dead:协同程序执行完毕,或没有更多的操作。
状态查看 API
函数 描述
coroutine.status(co) 返回协同程序的状态
coroutine.running() 返回当前正在运行的协同程序

1.2 使用协同程序的基本 API

函数 描述
coroutine.create(func) 创建新的协同程序,返回协同程序句柄
coroutine.resume(co, ...) 恢复协同程序的运行,可以传递参数
coroutine.yield(...) 暂停协同程序的运行,返回给调用者
coroutine.status(co) 获取协同程序的状态
coroutine.running() 返回当前正在运行的协同程序句柄和是否是主协同程序
coroutine.wrap(func) 创建一个协同程序,并返回一个可以直接调用的函数

2. 协同程序的基本使用

2.1 创建和运行协同程序

协同程序通过 coroutine.create() 创建,然后使用 coroutine.resume() 启动或恢复运行。

示例:基本协同程序
local co = coroutine.create(function()
    print("Inside coroutine")
end)

print(coroutine.status(co)) -- 输出:suspended
coroutine.resume(co)         -- 输出:Inside coroutine
print(coroutine.status(co)) -- 输出:dead

2.2 暂停和恢复协同程序

协同程序可以在运行过程中调用 coroutine.yield() 暂停自身,并将控制权交回调用者。随后可以通过 coroutine.resume() 恢复运行。

示例:暂停与恢复
local co = coroutine.create(function()
    for i = 1, 3 do
        print("Step", i)
        coroutine.yield() -- 暂停协同程序
    end
end)

coroutine.resume(co) -- 输出:Step 1
coroutine.resume(co) -- 输出:Step 2
coroutine.resume(co) -- 输出:Step 3
print(coroutine.status(co)) -- 输出:dead

2.3 传递参数和返回值

通过 coroutine.resume() 可以向协同程序传递参数,协同程序也可以通过 coroutine.yield() 返回值。

示例:协同程序参数和返回值

local co = coroutine.create(function(a, b)
    print("Start coroutine", a, b)
    local sum = a + b
    local result = coroutine.yield(sum) -- 暂停并返回 sum
    print("Resumed with", result)
end)

-- 第一次恢复
local status, sum = coroutine.resume(co, 10, 20)
print("Sum:", sum) -- 输出:Sum: 30

-- 第二次恢复
coroutine.resume(co, "Hello") -- 输出:Resumed with Hello

3. 高级用法

3.1 使用 coroutine.wrap

coroutine.wrap 创建一个协同程序,并返回一个可以直接调用的函数,无需显式调用 resume

示例:coroutine.wrap

local co = coroutine.wrap(function()
    for i = 1, 3 do
        print("Step", i)
        coroutine.yield()
    end
end)

co() -- 输出:Step 1
co() -- 输出:Step 2
co() -- 输出:Step 3

3.2 嵌套协同程序

协同程序可以在运行时调用另一个协同程序,实现嵌套协作。

示例:嵌套调用

local co1 = coroutine.create(function()
    print("In co1")
    coroutine.yield()
    print("Back to co1")
end)

local co2 = coroutine.create(function()
    print("In co2")
    coroutine.resume(co1) -- 恢复 co1 
    print("Back to co2")
end)

coroutine.resume(co2)

输出:

In co2
In co1
Back to co2
Back to co1

3.3 实现生产者-消费者模型

协同程序可以用于实现生产者-消费者模型,其中一个协同程序生成数据,另一个协同程序消费数据。

示例:生产者-消费者

local function producer()
    return coroutine.create(function()
        for i = 1, 5 do
            print("Producing", i)
            coroutine.yield(i) -- 暂停并返回生产的值
        end
    end)
end

local function consumer(prod)
    while true do
        local status, value = coroutine.resume(prod)
        if not status then break end
        print("Consuming", value)
    end
end

local prod = producer()
consumer(prod)

输出:

Producing 1
Consuming 1
Producing 2
Consuming 2
Producing 3
Consuming 3
Producing 4
Consuming 4
Producing 5
Consuming 5

3.4 用协同程序实现迭代器

协同程序可以实现自定义的迭代器,用于生成序列。

示例:生成器

local function range(start, stop, step)
    return coroutine.wrap(function()
        for i = start, stop, step do
            coroutine.yield(i)
        end
    end)
end

for i in range(1, 10, 2) do
    print(i)
end

输出:

1
3
5
7
9

4. 协同程序的应用场景

4.1 异步任务协调

协同程序可以用来模拟异步任务的行为,比如网络请求、文件操作等。

示例:任务调度器

local tasks = {}

local function create_task(func)
    local co = coroutine.create(func)
    table.insert(tasks, co)
end

local function run_tasks()
    while #tasks > 0 do
        local co = table.remove(tasks, 1)
        local status = coroutine.resume(co)
        if coroutine.status(co) ~= "dead" then
            table.insert(tasks, co)
        end
    end
end

-- 定义任务
create_task(function()
    for i = 1, 3 do
        print("Task 1 - Step", i)
        coroutine.yield()
    end
end)

create_task(function()
    for i = 1, 2 do
        print("Task 2 - Step", i)
        corout
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

小宝哥Code

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值