您的位置:首页 > 编程语言 > Lua

Lua学习笔记12:协同程序基础

2020-06-05 05:18 260 查看

协同程序同线程差不多,就是一条执行序列。
拥有自己独立的栈、局部变量和指令指针。
同时又和其他的协同程序共享全局变量和其他大部分东西。
从概念上来讲,线程与协同程序的主要区别在于,一个具有多线程的程序可以同时运行多个线程;而协同程序却是需要彼此协作来运行,即一个具有多个程序的协同程序在任一指定时刻只有一个协同程序在运行,并且协同程序只有被显示地(执行挂起函数)要求挂起才会暂停。
Lua将所有关于协同程序的函数放入名为“coroutine”的table中,函数create创建新的协同程序,它只有一个参数,该函数的代码是协同程序所需执行的内容;create会返回一个thread类型的值,用于表示新的协同程序;通常create的参数是一个匿名函数。
相关函数:协同程序的相关函数都存放在全局的table变量coroutine中

一、create(方法函数):用于创建协同程序,只有一个参数,就是一个函数(一般为匿名函数),函数中的代码就是协同程序将要执行的内容。create返回值的类型为thread。创建后的协同程序处于挂起状态。
例:co = coroutine.create ( function()  print("Hi")  end )  --创建协同程序
Lua的四种状态:
(1)挂起(suspended):创建时或执行了操作coroutine.yield()
(2)运行(running):执行了coroutine.resume()
(3)死亡(dead):最后一次调用resume时,协同程序的内容已执行完毕,并且已经返回。resume状态为dead的协同程序将返回false及错误消息,不再执行主函数体。
(4)正常(normal):当一个协同程序A唤醒另一个协同程序B时,A就处于一种特殊状态——既不是挂机状态(A不能继续执行),也不是运行状态(B在运行)。
当创建一个协同程序时,处于挂起状态,不会自动执行内容。可以通过status函数来检查协同程序的状态。coroutine.status(x)

二、函数coroutine.resume(线程名)可以使程序由挂起状态变为运行态,resume在保护模式中运行;(1)激活coroutine,也就是让协程函数开始运行;(2)唤醒yield,使挂起的协同接着上次的地方继续运行。该函数可以传入参数
resume(co,...):启动或再次启动协同程序。参数列表中:co表示将要被启动的协同程序,后面为变长的可选参数。
----------------------------------------
挂起态:创建一个协同程序时他开始的状态为挂起态,函数coroutine.yield可以使程序由运行态变为挂起状态,之后还可以再恢复其运行。
运行态:函数coroutine.resume可以使程序由挂起状态变为运行态,resume在保护模式中运行。
死亡态:协同程序的运行态结束后,协同程序结束,进入停止态。

三、yield(...):使正在运行的协同程序挂起,之后可以再恢复运行(调用resume)。只能被协同程序的主函数调用(即在协同程序执行的内容中调用)。参数列表为可选的变长参数。
例:
co = coroutine.create (function () 
    for i = 1, 10 do
        print("co",i)
        coroutine.yield()  -->将该协同程序挂起,之后使用coroutine.resuime(co)即可再次运行该协同程序
    end
end)
注意:resume在保护模式下运行,因此,如果协同程序内部存在错误,Lua并不会抛出错误,而是将错误返回给resume函数调用。
Lua的协同程序还有一项很有用的机制:通过一对resume-yield交换数据
(1)在第一次调用resume时并没有yield在等待它,因此所有传递给resume的额外参数(...)都将视为协同程序主函数的参数。
例:
co = coroutine.create ( function(a,b)  print("co:",a,b)  end )  --创建协同程序
coroutine.resume(co,10,20)  --> co:10  20  --启动协同程序,其中10,20就是额外参数,传递给了协同程序的主函数(匿名函数)
(2)resume的返回值中包含传递给yield的所有参数。如:
 co = coroutine.create( function(a,b)
                                     coroutine.yield(a+b,a-b)  --在协同程序的主函数中直接调用yield
                                     end ) 
第一次调用resume:print(coroutine.resume(co,20,10)) -->true  30  10   --返回值为true表示协同程序执行完毕或执行到yield之前没有发生错误,后面的返回值就是传递给yield的参数。
(3)yield的返回值就是对应resume传入的额外参数。如:
co = coroutine.create( function() print("co:",coroutine.yield()) end)
coroutine.resume(co) -->   --resume中没有额外参数,则yield不会有返回值,协同程序挂起
coroutine.resume(co,4,5)    --resume中有额外参数,则先返回co   4    5,然后协同程序挂起
4)当协同程序结束时,它的主函数返回的值都将作为resume的返回值。如:
co = coroutine.create( function() return 1,2 end )
print(coroutine.resume(co)) -->true 1  2 

五、Lua提供的协同程序称为非对称的协同程序(asymmetric coroutines),Lua提供了两个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行,"挂起一个正在执行的协同程序函数"(yield)与"使一个被挂起的协同程序再次执行的函数"(resume);有些语言提供对称协同(symmetric coroutines),即使用同一个函数负责“执行与挂起间的状态切换”(负责转让协同程序之间的执行权)。
 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: