好贷网好贷款

Lua 协程随笔

发布时间:2016-12-5 6:33:26 编辑:www.fx114.net 分享查询网我要评论
本篇文章主要介绍了"Lua 协程随笔",主要涉及到Lua 协程随笔方面的内容,对于Lua 协程随笔感兴趣的同学可以参考一下。

协同程序 coroutine  [,kəuru:'ti:n] 1、概念      协同程序类似多线程情况下的线程,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。线程程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。就是说,一个具有多个协同程序的程序在任何时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显示地挂起时,它的执行才会暂停。      lua虽然是单线程,串行执行的脚步语言,但利用协程还是可以实现一些异步处理的特性。协同程序可以简化看出是一个复杂的调用函数的方式(协程内部就是一个函数方法),它的核心是 yield 函数,yield函数可以将正在运行的代码(协同内部的函数)挂起,处理其他事务,处理完成再次唤醒该协程,      Lua语言实现的协程是一种非对称式(asymmetric)协程,或称半对称式(semi-symmetric)协程,又或干脆就叫半协程(semi-coroutine)。这种协程机制之所以被称为非对称的,是因为它提供了两种传递程序控制权的操作:一种是(重)调用协程(通过coroutine.resume);另一种是挂起协程并将程序控制权返回给协程的调用者(通过coroutine.yield)。一个非对称协程可以看做是从属于它的调用者的,二者的关系非常类似于例程(routine)与其调用者之间的关系。既然有非对称式协程,当然也就有对称式(symmetric)协程了,它的特点是只有一种传递程序控制权的操作,即将控制权直接传递给指定的协程。曾经有这么一种说法,对称式和非对称式协程机制的能力并不等价,但事实上很容易根据前者来实现后者。 2、特性      优点 由于是假的线程,所以切换线程的开销极小,且不用线程调度所以可以更充分利用cpu。每个coroutine有自己私有的stack及局部变量,相当于一个小的执行环境。同一时间只有一个coroutine在执行,无需对全局变量加锁,但因为共享全局变量所以在被挂起期间是可能被其他协程修改。顺序可控,完全由程序控制执行的顺序。而通常的多线程一旦启动,它的运行时序是没法预测的,因此通常会给测试所有的情况带来困难。      缺点           因为lua本质还是是单线程,所以一个协程阻塞会堵住所有的协程,也就是说协程内部如果也被阻塞的话就会导致整个应用阻塞(协同并非真正意义的多线程)。 3、使用 coro = coroutine.create(function(...) -- do xxx print(coroutine.status(coro)); -- running print("run data" .. arg[1]); local status, result = coroutine.yield(os.time()); print("status = " .. status); print("result = " .. result); end) print(type(coro)); -- thread -- 协程的三个状态 挂起(suspended) 运行(running) 停止(dead) print(coroutine.status(coro)); -- suspended local result, startTime = coroutine.resume(coro, 1); -- startTime保存yield的第一个参数 'os.time()' print(result, startTime); print(coroutine.status(coro)); -- suspended local result = coroutine.resume(coro, 1, "success");            在执行到yield之后,代码跳转到上一次resume代码的后一条代码执行      再次调用resume,代码就跳转到上一次yield代码的后一条代码执行。      一般来说,resume方法在主线程中调用;而yield则是在coroutine内调用,包括coroutine内部调用的函数内部.      在coroutine中调用resume没有什么问题,但这样是没有什么意义的      在main线程不能调用yield,会导致 “lua: attempt to yield across metamethod/C-call boundary”的错误。 4、应用场景       感觉最大的应用场景主要是可以替代回调机制,当需要异步执行等待返回结果的的时候,先启动一个协程,待发出请求后将协程挂起去处理其他事务。异步结果完成后再返回请求的结果到该协程,唤醒该协程继续执行,看上去就像是"发送请求","请求返回","处理返回结果",能在很大程度上提高代码可读性和减少代码量。       另外一个应用是复杂的迭代器,比如二叉树的前序遍历: function preOrder(node) if node then preOrder(node.left); coroutine.yield(node.key, node.value); preOrder(node.right); end end function createIter(node) do return coroutine.wrap( function() preOrder(node); return nil; end; end for k,v in createIter(tree) do print(k, v); end

上一篇:最小树形图
下一篇:需求开发与需求管理

相关文章

关键词: Lua 协程随笔

相关评论