关于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)
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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 14,759评论 0 38
  • 我们首先介绍一下什么是协程、然后详细介绍一下coroutine库,然后介绍一下协程的简单用法,最后介绍一下协程的复...
    17269780ceda阅读 4,082评论 0 6
  • “协程(coroutine)”于我而言还是比较新的概念,Lua 也是刚接触不久。不过碰巧这段时间我又在看 ES6 ...
    NARUTO_86阅读 5,645评论 0 3
  • lua中的另一个高级功能是coroutine(协程),协同式多线程的意思,不同于线程和进程,协程仅在显示的调用一个...
    ytlm阅读 11,819评论 0 2
  • 并发是现实世界的本质特征,而聪明的计算机科学家用来模拟并发的技术手段便是多任务机制。多任务机制大致可划分为两种: ...
    JunChow520阅读 7,900评论 0 4

友情链接更多精彩内容