【深入Lua】理解Lua中最强大的特性-coroutine(协程)
来源:互联网 发布:seo网络营销推广工资 编辑:程序博客网 时间:2024/05/20 14:18
http://my.oschina.net/wangxuanyihaha/blog/186401
coroutine基础
Lua所支持的协程全称被称作协同式多线程(collaborative multithreading)。Lua为每个coroutine提供一个独立的运行线路。然而和多线程不同的地方就是,coroutine只有在显式调用yield函数后才被挂起,同一时间内只有一个协程正在运行。
Lua将它的协程函数都放进了coroutine这个表里,其中主要的函数如下
摘取一段云风的代码来详尽解释协程的工作机制,在这段代码中,展示了main thread和协程co之间的交互:
function foo(a) print("foo", a) return coroutine.yield(2 * a)endco = coroutine.create(function ( a, b ) print("co-body", a, b) local r = foo(a + 1) print("co-body", r) local r, s = coroutine.yield(a + b, a - b) print("co-body", r, s) return b, "end"end)print("main", coroutine.resume(co, 1, 10))print("main", coroutine.resume(co, "r"))print("main", coroutine.resume(co, "x", "y"))print("main", coroutine.resume(co, "x", "y"))
下面是运行结果
co-body 1 10foo 2main true 4co-body rmain true 11, -9co-body x ymain false 10 endmain false cannot resume dead coroutine
coroutine和subroutine(子例程)的比较
子例程的起始处是唯一的入口点,一旦return就完成了子程序的执行,子程序的一个实例只会运行一次。
但是协程不一样,协程可以使用yield来切换到其他协程,然后再通过resume方法重入(reenter)到上次调用yield的地方,并且把resume的参数当成返回值传给了要重入(reenter)的协程。但是coroutine的状态都没有被改变,就像一个可以多次返回的subroutine
,
协程的精妙之处就在于协作
这一概念,下面我们用生产者和消费者问题来演示一下协程的基本应用。注意:下面的伪码是用Lua的思想写的
var q = queue()
生产者的伪码
loop while q is not full create product add the items to q resume to consumer
消费者的伪码
loop while q is not empty consume product remove the items from q yield
coroutine的和callback的比较
coroutine经常被用来和callback进行比较,因为通常来说,coroutine和callback可以实现相同的功能,即异步通信,比如说下面的这个例子:
bob.walkto(jane)bob.say("hello")jane.say("hello")
看起来好像是对的,但实际上由于这几个动作walkto,say都是需要一定时间才能做完的
,所以这段程序如果这样写的话,就会导致bob一边走一边对jane说hello,然后在同时jane也对bob说hello,导致整个流程十分混乱。
如果使用回调来实现的话,代码示例如下:
bob.walto(function ( ) bob.say(function ( ) jane.say("hello") end,"hello")end, jane)
即walto函数回调say函数,say函数再回调下一个say函数,这样回调看起来十分混乱,让人无法一下看出这段代码的意义.
如果用coroutine的话,可以使用如下写法:
co = coroutine.create(function ( ) local current = coroutine.running bob.walto(function ( ) coroutine.resume(current) end, jane) coroutine.yield() bob.say(function ( ) coroutine.resume(current) end, "hello") coroutine.yield() jane.say("hello")end)coroutine.resume(co)
在上述代码中,一旦一个异步函数被调用,协程就会使用coroutine.yield()方法将该协程暂时悬挂起来,在相应的回调函数中加上coroutine.resume(current),使其返回目前正在执行的协程中。
但是,上述代码中有许多重复的地方,所以可以通过将封装的方式将重复代码封装起来
function runAsyncFunc( func, ... ) local current = coroutine.running func(function ( ) coroutine.resume(current) end, ...) coroutine.yield()endcoroutine.create(function ( ) runAsyncFunc(bob.walkto, jane) runAsyncFunc(bob.say, "hello") jane.say("hello")end)coroutine.resume(co)
这样就不需要改变从前的所有回调函数,即可通过携程的方式解决异步调用的问题,使得代码的结构非常清晰。
- 【深入Lua】理解Lua中最强大的特性-coroutine(协程)
- 【深入Lua】理解Lua中最强大的特性-coroutine(协程)
- 理解Lua的Coroutine
- Lua coroutine理解
- lua coroutine理解
- LUA 怎么理解coroutine ?
- Lua协程(coroutine)的基本知识
- Lua基础coroutine(协程)
- lua的coroutine
- Lua 协程 coroutine
- lua协程coroutine
- LuaBind --最强大的Lua C++ Bind
- LuaBind --最强大的Lua C++ Bind
- LuaBind --最强大的Lua C++ Bind
- LuaBind --最强大的Lua C++ Bind
- LuaBind --最强大的Lua C++ Bind
- LuaBind --最强大的Lua C++ Bind
- LuaBind --最强大的Lua C++ Bind
- 软件架构和设计
- Lua 标准库 - 基本函数(base function)
- 关于附带数据库操作时Activity界面总是自动启动
- Java web项目中jsp使用java类的方法
- tomcat connector运行模式,优化tomcat运行性能
- 【深入Lua】理解Lua中最强大的特性-coroutine(协程)
- 苹果审核reject理由大全(5):IAP商品在iphone、ipad版本互通
- 2015 多校联赛 ——HDU5371(manacher + 枚举)
- 有关ip地址转int型存储需要注意的地方
- 记录每天的收获与总结
- 软件架构设计应该考虑的问题(优秀)
- leetCode #58 Length of Last Word
- linux(debian/ubuntu)下连接安卓手机--小米4为例
- 数据结构基本概念