Appearance
协同程序(coroutine)
协同程序(coroutine)是 Lua 中实现并发的机制,它允许在不同的执行流之间切换。本章节将介绍 Lua 中协同程序的概念、使用方法和常见应用。
协同程序的基本概念
协同程序是一种特殊的函数,它可以在执行过程中暂停,然后在稍后的某个时间点恢复执行。与线程不同,协同程序是协作式的,而不是抢占式的,也就是说,协同程序只有在显式地调用 yield 函数时才会暂停执行。
协同程序的创建和使用
创建协同程序
使用 coroutine.create 函数创建协同程序:
lua
local co = coroutine.create(function()
print("协同程序开始执行")
coroutine.yield()
print("协同程序恢复执行")
end)启动协同程序
使用 coroutine.resume 函数启动或恢复协同程序:
lua
print("启动协同程序")
coroutine.resume(co)
print("协同程序暂停")
coroutine.resume(co)
print("协同程序执行完毕")输出:
启动协同程序
协同程序开始执行
协同程序暂停
协同程序恢复执行
协同程序执行完毕协同程序的状态
协同程序有四种状态:
suspended:协同程序已创建但尚未启动,或已暂停running:协同程序正在执行dead:协同程序执行完毕normal:协同程序正在执行,但不是当前协同程序
使用 coroutine.status 函数查看协同程序的状态:
lua
local co = coroutine.create(function()
print("协同程序开始执行")
coroutine.yield()
print("协同程序恢复执行")
end)
print(coroutine.status(co)) -- 输出 suspended
coroutine.resume(co)
print(coroutine.status(co)) -- 输出 suspended
coroutine.resume(co)
print(coroutine.status(co)) -- 输出 dead协同程序的参数和返回值
向协同程序传递参数
可以在 coroutine.resume 中向协同程序传递参数:
lua
local co = coroutine.create(function(a, b)
print("协同程序开始执行,参数:" .. a .. ", " .. b)
local c, d = coroutine.yield(a + b)
print("协同程序恢复执行,参数:" .. c .. ", " .. d)
return a + b + c + d
end)
local status, result = coroutine.resume(co, 10, 20)
print("第一次 resume 返回:" .. status .. ", " .. result)
local status, result = coroutine.resume(co, 30, 40)
print("第二次 resume 返回:" .. status .. ", " .. result)输出:
协同程序开始执行,参数:10, 20
第一次 resume 返回:true, 30
协同程序恢复执行,参数:30, 40
第二次 resume 返回:true, 100协同程序的返回值
协同程序的返回值会作为 coroutine.resume 的返回值:
lua
local co = coroutine.create(function()
return "Hello", "World"
end)
local status, result1, result2 = coroutine.resume(co)
print(status, result1, result2) -- 输出 true Hello World协同程序的应用
示例 1:实现迭代器
lua
function values(t)
local i = 0
return coroutine.create(function()
i = i + 1
while i <= #t do
coroutine.yield(t[i])
i = i + 1
end
end)
end
local fruits = {"苹果", "香蕉", "橙子", "葡萄"}
local co = values(fruits)
while true do
local status, value = coroutine.resume(co)
if not status then
break
end
print(value)
end输出:
苹果
香蕉
橙子
葡萄示例 2:实现生产者-消费者模式
lua
function producer()
return coroutine.create(function()
for i = 1, 5 do
print("生产:" .. i)
coroutine.yield(i)
end
end)
end
function consumer(prod)
while true do
local status, value = coroutine.resume(prod)
if not status then
break
end
print("消费:" .. value)
end
end
local prod = producer()
consumer(prod)输出:
生产:1
消费:1
生产:2
消费:2
生产:3
消费:3
生产:4
消费:4
生产:5
消费:5示例 3:实现非阻塞 IO
lua
function readFile(filename)
return coroutine.create(function()
local file = io.open(filename, "r")
if not file then
coroutine.yield("文件不存在")
return
end
local content = file:read("*")
file:close()
coroutine.yield(content)
end)
end
local co = readFile("test.txt")
local status, content = coroutine.resume(co)
if status then
print(content)
else
print("错误:" .. content)
end协同程序的高级应用
示例 1:实现状态机
lua
function stateMachine()
return coroutine.create(function()
while true do
print("状态 1")
coroutine.yield(1)
print("状态 2")
coroutine.yield(2)
print("状态 3")
coroutine.yield(3)
end
end)
end
local sm = stateMachine()
for i = 1, 5 do
local status, state = coroutine.resume(sm)
print("当前状态:" .. state)
end输出:
状态 1
当前状态:1
状态 2
当前状态:2
状态 3
当前状态:3
状态 1
当前状态:1
状态 2
当前状态:2示例 2:实现协程池
lua
local function createCoroutinePool(size, func)
local pool = {}
for i = 1, size do
local co = coroutine.create(func)
table.insert(pool, co)
end
return pool
end
local function worker()
while true do
local task = coroutine.yield()
print("执行任务:" .. task)
end
end
local pool = createCoroutinePool(3, worker)
local tasks = {"任务 1", "任务 2", "任务 3", "任务 4", "任务 5"}
for i, task in ipairs(tasks) do
local co = pool[(i - 1) % #pool + 1]
coroutine.resume(co, task)
end输出:
执行任务:任务 1
执行任务:任务 2
执行任务:任务 3
执行任务:任务 4
执行任务:任务 5小结
本章节介绍了 Lua 中协同程序的概念、创建和使用方法、状态、参数和返回值,以及协同程序在实现迭代器、生产者-消费者模式、非阻塞 IO、状态机和协程池等方面的应用。掌握协同程序的使用,对于编写 Lua 程序非常重要。