Lua 协程随笔
2013-08-31 19:01
232 查看
协同程序
协同程序类似多线程情况下的线程,也就是一条执行序列,拥有自己独立的栈,局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。线程程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。就是说,一个具有多个协同程序的程序在任何时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显示地挂起时,它的执行才会暂停。
lua虽然是单线程,串行执行的脚步语言,但利用协程还是可以实现一些异步处理的特性。协同程序可以简化看出是一个复杂的调用函数的方式(协程内部就是一个函数方法),它的核心是 yield 函数,yield函数可以将正在运行的代码(协同内部的函数)挂起,处理其他事务,处理完成再次唤醒该协程,
Lua语言实现的协程是一种非对称式(asymmetric)协程,或称半对称式(semi-symmetric)协程,又或干脆就叫半协程(semi-coroutine)。这种协程机制之所以被称为非对称的,是因为它提供了两种传递程序控制权的操作:一种是(重)调用协程(通过coroutine.resume);另一种是挂起协程并将程序控制权返回给协程的调用者(通过coroutine.yield)。一个非对称协程可以看做是从属于它的调用者的,二者的关系非常类似于例程(routine)与其调用者之间的关系。既然有非对称式协程,当然也就有对称式(symmetric)协程了,它的特点是只有一种传递程序控制权的操作,即将控制权直接传递给指定的协程。曾经有这么一种说法,对称式和非对称式协程机制的能力并不等价,但事实上很容易根据前者来实现后者。
2、特性
优点
由于是假的线程,所以切换线程的开销极小,且不用线程调度所以可以更充分利用cpu。
每个coroutine有自己私有的stack及局部变量,相当于一个小的执行环境。
同一时间只有一个coroutine在执行,无需对全局变量加锁,但因为共享全局变量所以在被挂起期间是可能被其他协程修改。
顺序可控,完全由程序控制执行的顺序。而通常的多线程一旦启动,它的运行时序是没法预测的,因此通常会给测试所有的情况带来困难。
缺点
因为lua本质还是是单线程,所以一个协程阻塞会堵住所有的协程,也就是说协程内部如果也被阻塞的话就会导致整个应用阻塞(协同并非真正意义的多线程)。
3、使用
在执行到yield之后,代码跳转到上一次resume代码的后一条代码执行
再次调用resume,代码就跳转到上一次yield代码的后一条代码执行。
一般来说,resume方法在主线程中调用;而yield则是在coroutine内调用,包括coroutine内部调用的函数内部.
在coroutine中调用resume没有什么问题,但这样是没有什么意义的
在main线程不能调用yield,会导致 “lua: attempt to yield across metamethod/C-call boundary”的错误。
4、应用场景
感觉最大的应用场景主要是可以替代回调机制,当需要异步执行等待返回结果的的时候,先启动一个协程,待发出请求后将协程挂起去处理其他事务。异步结果完成后再返回请求的结果到该协程,唤醒该协程继续执行,看上去就像是"发送请求","请求返回","处理返回结果",能在很大程度上提高代码可读性和减少代码量。
另外一个应用是复杂的迭代器,比如二叉树的前序遍历:
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
相关文章推荐
- C/C++ 调用 Lua (学习随笔)
- Lua中的协程Coroutine
- Lua基础之coroutine(协程)
- Lua程序设计(第2版)第四章学习随笔——语句
- Lua协程
- ngx_lua中的协程调度(四)
- 明明白白lua的协程(coroutine)
- ngx_lua中的协程调度(二)
- 【深入Lua】理解Lua中最强大的特性-coroutine(协程)
- lua协程的使用(二)
- Lua笔记——迭代器、协程、面向对象
- [Unity] Unity的lua项目中模拟每帧运行一次的协程
- Lua的协程(coroutine)
- Lua语言学习之协程
- lua学习随笔 (1)
- lua服务执行过程中协程的挂起和重新唤醒
- 《Lua 5.0的实现》第六章 - 线程和协程
- 对lua协程的一点理解
- Lua 初学者随笔 一
- (zt)Lua的多任务机制——协程(coroutine)