关于Lua中协程coroutine的理解

关于Lua中协程coroutine的理解_第1张图片
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)
end

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

参考

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

你可能感兴趣的:(关于Lua中协程coroutine的理解)