Lua 基础之协同程序
来源:互联网 发布:angularjs2 seo问题 编辑:程序博客网 时间:2024/06/15 00:38
协同程序
- 协同程序类似于多线程中的线程。lua 提供 非对称的协同程序 ,即 lua 提供两个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。
- 协同程序的函数放置在表 coroutine 中,创建时传入一个函数,生成一个 thread 类型的值
- 协同程序的四种状态:挂起(suspended),运行(running)、死亡(dead),正常(normal)
- 使用 status 函数来查看协程的状态,协程创建时的状态是 挂起
- 使用 resume 函数可以唤醒协程,将其状态由 挂起 变为 运行
- 如果协程执行一次就完了,那它的状态就会变成 死亡
- 使用 yield 函数来挂起协程,将其状态由 运行 变为 挂起
- 当协程 A 唤醒另一个协程 B 时,A 就处于一个特殊的状态,称为 正常
- 协程的挂起操作发生在 yield 函数中,也就是说协程运行到 yield 函数时暂停,没有从 yield 函数返回,当下次执行 resume 的时候才从 yield 返回,然后继续执行,直到遇到下一次 yield 或协程运行结束
local mod = ...local m = {}_G[mod] = mpackage.loaded[mod] = mm.main = function() while coroutine.status(m.co) ~= [[dead]] do io.read() coroutine.resume(m.co) endendm.co = coroutine.create( function() for i = 1, 10 do print("co", i) coroutine.yield() end end)
使用 resume-yield 交换数据
- 第一次唤醒协程,resume 参数传给协程主函数
coroutine.resume(m.co2, 1, 2, 3)coroutine.resume(m.co2, 10, 20, 30)m.co2 = coroutine.create( function(a, b, c) while true do print("co", a, b, c) coroutine.yield() end end)
co 1 2 3
co 1 2 3
从输出结果可以看出,第一次调用 resume 时,参数的值传给了 a,b,c,第二次调用时则不会
- yield 传入的参数值传给 resume
print(coroutine.resume(m.co2, 1, 2, 3))print(coroutine.resume(m.co2, 10, 20, 30))m.co2 = coroutine.create( function(a, b, c) while true do print("co", a, b, c) coroutine.yield(a + b, a + c, b + c) end end)
co 1 2 3
true 3 4 5
co 1 2 3
true 3 4 5
- yield 的返回值是 resume 传入的参数
print(coroutine.resume(m.co2, 1, 2, 3))print(coroutine.resume(m.co2, 10, 20, 30))m.co2 = coroutine.create( function(a, b, c) while true do print("co", coroutine.yield()) end end)
true
co 10 20 30
true
第一次调用 resume 时,传入的参数 1,2,3 被参数 a,b,c 接收了,然后协程在 yield 函数中挂起,第二次调用 resume,传入的 10,20,30 作为 yield 的返回值,yield 返回到协程继续执行,输出 co 10 20 30
- 协程运行完毕,主函数返回值传给 resume
print(coroutine.resume(m.co2, 1, 2, 3))print(coroutine.resume(m.co2, 10, 20, 30))m.co2 = coroutine.create( function(a, b, c) coroutine.yield() return a + b + c end)
true
true 6
总结
- resume 第一次执行,参数传给协程主函数
- resume 再次执行,参数作为 yield 的返回值
- 协程挂起时 yield 的参数作为 resume 的返回值
- 协程死亡时主函数的返回值作为 resume 的返回值
生产者-消费者
生产者-消费者是一个经典的协同程序,生产者不停地生产值,然后发送给消费者;消费者不停地接收值,然后催促生产者生产;两者都有自己的主循环,都把自己当作调用的主动方,但实际程序只能有一方是主动方,而另一方则必须由主动方来唤醒,执行一次之后挂起,下面就是一个 消费者驱动 的例子
-- 生产者设计成协程m.producer = coroutine.create( function() while true do local value = tonumber(io.read()) if value == -1 then break end -- 生产者生产值之后挂起 coroutine.yield(value) end end)-- 消费者驱动m.customer = function() while true do -- 消费者唤醒生产者 local status, value = coroutine.resume(m.producer) if status == false or coroutine.status(m.producer) == "dead" then break end io.write(value, "\n") endend
可以在生产者和消费者之前加一个过滤器。生产者是一个协程,过滤器也是一个协程;然后消费者唤醒过滤器,过滤器再唤醒生产者,生产者产生值之后就挂起自己,过滤器接收生产的值后也挂起自己,最后消费者接收生产的值后继续唤醒过滤器
-- 生产者设计成协程m.producer = function() return coroutine.create( function() while true do local value = io.read() if value == "-1" then break end -- 生产者生产值之后挂起 coroutine.yield(value) end end )end-- 过滤器设计成协程m.filter = function(producer) return coroutine.create( function() for line = 1, math.huge do -- 唤醒生产者 local status, value = coroutine.resume(producer) -- 生产者死亡 if status == false or coroutine.status(producer) == "dead" then break end x = string.format("%-5d %s", line, value) -- 过滤器得到生产值之后挂起 coroutine.yield(x) end end )end-- 消费者驱动m.customer = function(filter) while true do -- 唤醒过滤器 local status, value = coroutine.resume(filter) -- 过滤器死亡 if status == false or coroutine.status(filter) == "dead" then break end io.write(value, "\n") endend
阅读全文
0 0
- Lua 基础之协同程序
- Lua基础之协同程序(coroutine)
- Lua之协同程序
- lua之协同程序coroutine
- Cocos2d-Lua之协同程序
- Lua - Lua协同程序
- Lua学习笔记之协同程序
- 【笨木头Lua专栏】基础补充08:协同程序之resume-yield间的数据返回
- Lua 基础之 Lua 程序
- Lua的协同程序
- Lua的协同程序
- Lua的协同程序
- Lua的协同程序
- lua协同程序
- Lua协同程序coroutine
- lua协同程序探究
- lua 协同程序
- Lua协同程序
- NCURSES程序设计之魔数方阵
- Vuejs自己的构建工具
- ArrayList<Character>的删除问题
- windows内存体系结构
- Python之windows锁屏
- Lua 基础之协同程序
- 查找-二分查找(折半查找)-java
- 指针变量作函数参数,错误典例
- lintcode -- 最大子数组II
- RecyclerView和ListView的异同
- 关于SSL错误, SSLError: [Errno 1] _ssl.c:510: error:14090086:SSL routines
- 每天五分钟linux(5)-rm
- xUtils 多线程断点下载文件
- java定时器问题