关于Lua中协程coroutine的理解

关于Lua中协程coroutine的理解
文章图片
coroutine-resume-yield 一、 coroutine.resume()函数
用来首次启动或再次启动一个协程,使其由挂起状态变成运行状态。也可以这么说,resume函数相当于在执行协程中的方法。参数Val1...是执行协程co时传递给协程的参数。
(1) 首次调用resume执行协程co时,参数Val1...会赋值给协程co的函数,作为函数参数
(2) 以后再调用resume执行协程co时,参数Val1...会赋值给协程co中上一次yield的返回值
resume函数的返回有3种情况:
(1) 如果协程co的函数执行完毕,协程正常终止,resume 返回 true和函数的返回值。
(2) 如果协程co的函数执行过程中,协程让出了(调用了yield()方法),那么resume返回true和协程中调用yield传入的参数。
(3) 如果协程co的函数执行过程中发生错误,resume返回false与错误消息。
可以看到resume无论如何都不会导致程序崩溃。它是在保护模式下执行的
二、coroutine.yield()函数
使正在执行的协程挂起,注意是执行完该函数后才会使协程挂起
(1) yeild的参数会作为resume的第二个返回值
(2) 如果对该协程不是第一次执行resume,resume函数传入的参数将会作为yield的返回值
三、程序示例

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 110-- 协程co的第7行,此时resume()传入的参数是赋值给了函数的 foo 2-- 在第8行里面调用了函数foo(),执行到第2行的打印 maintrue4-- 由于函数foo()的第3行yield()执行后挂起,参数是4,作为第15行的resume()的第二个返回值,最终打印了出来,到此,第15行执行完毕 co-body r-- 第16行resume()再次唤醒协程co,接着上次yield()的地方继续执行,参数“r"被赋值给上次yield()的返回值,在第9行打印出来 maintrue11-9-- 在第10行yiled()后再次挂起协程co,并返回,此时参数a和b还是第一次resume()时的参数,1,10,所以yield()两个参数分别为11,-9,作为resum()的第二个返回值,最终被打印出来,到此,第16行执行完毕 co-body xy-- 第17行resume()再次唤醒协程co,传入的参数“x”,“y”被赋值给上次的yield()函数的返回值,即赋值给第10行的r,s,在第11行被打印出来 maintrue10end -- 协程co在第12行返回,注意此时参数b仍然是第一次resume()时的参数2,值为10,至此协程co执行结束,变为dead状态,最终在第17行打印出来 mainfalsecannot resume dead coroutine -- 第18行尝试再次resume()协程co,由于协程co已经为dead状态,所以直接返回并报错

四、Lua中协同的强大能力,在于通过resume-yield来交换数据:
(1)resume把参数传给程序(相当于函数的参数调用);
(2)数据由yield传递给resume;
(3)resume的参数传递给yield;
(4)协同代码结束时的返回值,也会传给resume
协同中的参数传递形势很灵活,一定要注意区分,在启动coroutine的时候,resume的参数是传给主程序的;在唤醒yield的时候,参数是传递给yield的。
co = coroutine.create(function (a, b) print("co", a, b, coroutine.yield()) end) coroutine.resume(co, 1, 2)--没输出结果,注意两个数字参数是传递给函数的 coroutine.resume(co, 3, 4, 5)--co 1 2 3 4 5,这里的两个数字参数由resume传递给yield 

参考
【关于Lua中协程coroutine的理解】1、Lua 协同程序(coroutine)
2、Lua中的协同程序 coroutine
3、深入理解lua的协程coroutine
4、Lua学习之coroutine总结
5、lua-Coroutine

    推荐阅读