协程
对于协同函数来说,可以在执行的时候在中间暂停(挂起),在后续某个时机可以让继续运行,可以任意的暂停继续
Lua协同程序与操作系统的概念比较类似,拥有独立的堆栈,独立的局部变量,独立的指针,同时又与其他的协同程序共享全局变量和公共资源
线程和协同程序的区别
一个具有多线程的程序可以同时运行多个线程,而协同程序需要彼此的协作运行,在任意指定时刻,只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求的时候才会被挂起
时间分割策略,解决游戏引擎单线程支持不足的问题
基本语法
- coroutine.create()
- 创建 coroutine,返回 coroutine,参数是一个函数,当和resume配合使用的时候可以唤醒函数调用
- coroutine.resume()
- 重启 coroutine 和 create 配合使用 让协程开始运作
- 唤醒 yield 在上次的地方继续执行
- coroutine.status
- running 运行中
- suspended 挂起协程,创建完成 和 被yield之后
- dead 函数走完之后,不能在执行resume
- coroutine.wrap()
- 创建一个 coroutine,返回一个函数,调用函数,会进入 coroutine 和 create 功能类似
- coroutine.running()
- 返回的是正在跑的coroutine,一个 coroutine 就是一个 thread 当使用running 的时候,返回的就是一个 coroutine 的线程号
案例
协同程序的创建和执行状态
function func1()
print(coroutine.status(cor))
print(100)
end
cor = coroutine.create(func1)
coroutine.resume(cor)
print(type(cor))
-- 结果
running
100
thread
print("=========================================================")
cor = coroutine.create(function(a)
print("a:" .. a)
end)
coroutine.resume(cor, "你好")
-- 结果
a:你好
print("=========================================================")
cor = coroutine.wrap(function(y)
print("y:" .. y)
end)
print(type(cor))
cor("我是y")
--结果
function
y:我是y
协程的 yield 语法 和 resume 语法
cor = coroutine.create(function()
for i = 1, 5 do
print("第几" .. i .. "次")
if i == 3 then
print("当前协程的状态" .. coroutine.status(cor))
print(coroutine.running())
end
coroutine.yield() -- 将线程设置为挂起状态,不在执行:等待下一个resume
end
end)
coroutine.resume(cor)
coroutine.resume(cor)
coroutine.resume(cor)
coroutine.resume(cor)
print("当前协程的状态:" .. coroutine.status(cor))
coroutine.resume(cor)
print("当前协程的状态:" .. coroutine.status(cor))
coroutine.resume(cor)
print("当前协程的状态:" .. coroutine.status(cor))
-- 结果
第几1次
第几2次
第几3次
当前协程的状态running
thread: 000000000067e348 false
第几4次
当前协程的状态:suspended
第几5次
当前协程的状态:suspended
当前协程的状态:dead
============================================
function func1(a)
print("func1得到的参数是: " .. a)
return coroutine.yield(a * 1000)
end
cor = coroutine.create(function(a, b)
print("第一次输出: ", a, b)
local r = func1(a + 1)
print("第二次输出: ", r)
local r, s = coroutine.yield(a + b, a - b)
print("第三次输出: ", r, s)
return b, "结束"
end)
-- yield中传入的参数,以resume的返回值返回出来
print(coroutine.resume(cor, 1, 10))
-- resume中传入进去的参数就相当于上一次挂起的时候yield的返回值
print(coroutine.resume(cor, 999))
print(coroutine.resume(cor, "我是r", "我是x"))
print(coroutine.resume(cor))
-- 结果
第一次输出: 1 10
func1得到的参数是: 2
true 2000
第二次输出: 999
true 11 -9
第三次输出: 我是r 我是x
true 10 结束
false cannot resume dead coroutine
Lua 的协程中 resume 与 yield 配合使用:
- 调用 resume,将协同程序唤醒,resume 操作成功返回true,否者返回false
- resume 可以把参数传递给协同程序,数据可以通过 yield 传递给 resume
- resume 的参数可以传递给协同程序,协同程序 代码结束时的返回值也会传递给 resume
- 协同程序 继续运行完成后 继续调用,resume方法输出 thread: false cannot resume dead coroutine
- resume 和 yield 配合的强大之处在于,resume处于主线程中,yield 处于分线程中,二者相互获取和调用
- resume 将外部状态(数据)传递到协同程序的内部,而 yield 则将内部的状态(数据)返回到外部