解析关于Lua协同程序 |
本文标签:Lua 协同 线程 关于Lua协同程序的内容是本文要介绍的内容,主要是来学习lua中线程的使用方法,关于系统程序,本文有详解,具体内容一起来看详解 。 1、什么是协同(coroutine)? 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,但是和其他协同程序共享全局变量等很多信息 。 协同和顺序执行的区别?任一制定时刻只能运行一个协同程序,这个和顺序执行区别在哪?关键在于yield函数 。如果顺序执行的时候进行耗费cpu时间或者一直等待某个资源的时候,程序将卡在这个地方不能前进 。协同程序的出现就是可以使等待资源的线程让出资源,进行下一个协同程序的操作 。yield可以在执行出错的时候挂起,下次恢复的时候再进行操作 。 2、协同(coroutine)的几个状态 挂起态:创建一个协同程序时他开始的状态为挂起态,函数coroutine.yield可以使程序由运行态变为挂起状态 运行态:函数coroutine.resume可以使程序由挂起状态变为运行态 停止态:协同程序结束,进入停止态 3、coroutine.resume resume可以给协同程序传参数,并将挂起态程序恢复为运行态
coroutine.resume直到线程结束或者遇到coroutine.yield时返回 。 (1)coroutine.resume的参数:线程函数第一次运行,参数作为线程函数参数;如果yield没有显式返回参数,则coroutine.resume的参数作为yield的额外参数返回 。 (2)如果是挂起状态(一开始也是挂起状态),继续运行resume函数返回true;如果线程已经停止或者遇到其他错误,resume函数返回false及错误信息 。 (3)线程结束则线程主函数的返回值作为coroutine.resume的附加返回值 。 这点特性很微妙,可以看出coroutine.resume其实是个阻塞函数,阻塞等待协同程序完成或者yield退出 。可以把协同程序当成一个等待对象,对象等待返回则coroutine.resume返回 。在coroutine.resume调用的地方阻塞调用线程,这个特性要记住! 4、coroutine.yield yield可以返回额外参数,或者挂起协同程序
使用函数yield可以使程序挂起并返回状态给resume,当我们激活被挂起的程序时,yield返回(这里的返回是说从阻塞状态返回)并继续程序的执行直到再次遇到yield或者程序结束 5、对称协同和不对称协同 对称协同:执行到挂起之间状态转换的函数是相同的 不对称协同:挂起一个正在执行的协同的函数与使一个被挂起的协同再次执行的函数是不同的(resum和yield) 当消费者需要值时他唤起生产者生产值,生产者生产值后停止直到消费者再次请求 。我们称这种设计为消费者驱动的设计 。平常多见的生产者-消费者模型,是产品驱动的设计,生产者不断生产产品,消费者用临界区保护取产品消费 协同为解决这种问题提供了理想的方法,因为调用者与被调用者之间的resume-yield关系会不断颠倒 。当一个协同调用yield时并不会进入一个新的函数,取而代之的是返回一个未决的resume的调用 。相似的,调用resume时也不会开始一个新的函数而是返回yield的调用 。这种性质正是我们所需要的,与使得send-receive协同工作的方式是一致的:receive唤醒生产者生产新值,send把产生的值送给消费者消费 。
看完上面这个例子你可能很自然的想到UNIX的管道,协同是一种非抢占式的多线程 。管道的方式下,每一个任务在独立的进程中运行,而协同方式下,每个任务运行在独立的协同代码中 。管道在读(consumer)与写(producer)之间提供了一个缓冲,因此两者相关的的速度没有什么限制,在上下文管道中这是非常重要的,因为在进程间的切换代价是很高的 。协同模式下,任务间的切换代价较小,与函数调用相当,因此读写可以很好的协同处理 。 小结:解析关于Lua协同程序的内容介绍完了,希望通过本文的学习能对你有所帮助! |