Lua协程

作者: 钟离惜 | 来源:发表于2020-12-03 20:43 被阅读0次

首先了解一下多线程。我们都知道线程——Thread。每一个线程都代表一个执行序列。当我们在程序中创建多线程的时候,看起来,同一时刻多个线程是同时执行的,不过实质上多个线程是并发的,因为只有一个CPU,所以实质上同一个时刻只有一个线程在执行。在一个时间片内执行哪个线程是不确定的,我们可以控制线程的优先级,不过真正的线程调度由CPU的调度决定。
协程跟线程都代表一个执行序列。不同的是,协程把线程中不确定的地方尽可能的去掉,执行序列间的切换不再由CPU隐藏的进行,而是由程序显式的进行。所以,使用协程实现并发,需要多个协程彼此协作。

coroutine.create(function)

传一个函数参数,用来创建协程。返回一个“thread”对象。

coroutine.isyieldable ()

如果正在运行的协程可以让出,则返回真。值得注意的是,只有主协程(线程)和C函数中是无法让出的。

coroutine.resume (co, Val1...)

这是一个非常重要的函数。用来启动或再次启动一个协程,使其由挂起状态变成运行状态。
可以这么说,resume函数相当于在执行协程中的方法。参数Val1...是执行协程co时传递给协程的方法。
首次执行协程co时,参数Val1...会传递给协程co的函数;
再次执行协程co时,参数Val1...会作为给协程co中上一次yeild的返回值。
不知道这句话大家理解了没,这是协程的核心。如果没理解也不用急,继续往下看,稍后我会详细解释。
resume函数返回什么呢?有3种情况:
  1)如果协程co的函数执行完毕,协程正常终止,resume 返回 true和函数的返回值。
  2)如果协程co的函数执行过程中,协程让出了(调用了yeild()方法),那么resume返回true和协程中调用yeild传入的参数。
  3)如果协程co的函数执行过程中发生错误,resume返回false与错误消息。
可以看到resume无论如何都不会导致程序崩溃。它是在保护模式下执行的。

coroutine.running ()

返回两个值,一个返回当前的线程ID,一个返回是否是主线程,下面的例子中有演示。

coroutine.status (co)

返回一个字符串,表示协程的状态。有4种状态:
  1)running。如果在协程的函数中调用status,传入协程自身的句柄,那么执行到这里的时候才会返回running状态。
  2)suspended。如果协程还未结束,即自身调用了yeild或还没开始运行,那么就是suspended状态。
  3)normal。如果协程Aresume协程B时,协程A处于的状态为normal。在协程B的执行过程中,协程A就一直处于normal状态。因为它这时候既不是挂起状态、也不是运行状态。
  4)dead。如果一个协程发生错误结束,或正常终止。那么就处于dead状态。如果这时候对它调用resume,将返回false和错误消息。

coroutine.wrap (f)

wrap()也是用来创建协程的。只不过这个协程的句柄是隐藏的。跟create()的区别在于:
  1)wrap()返回的是一个函数,每次调用这个函数相当于调用coroutine.resume()。
  2)调用这个函数相当于在执行resume()函数。
  3)调用这个函数时传入的参数,就相当于在调用resume时传入的除协程的句柄外的其他参数。
  4)调用这个函数时,跟resume不同的是,它并不是在保护模式下执行的,若执行崩溃会直接向外抛出。

coroutine.yield (···)

使正在执行的函数挂起。
传递给yeild的参数会作为resume的额外返回值。
同时,如果对该协程不是第一次执行resume,resume函数传入的参数将会作为yield的返回值。

例1:resume、yield使用

coco = coroutine.create(function (a,b)
    print("resume args:"..a..","..b)
    yreturn = coroutine.yield()
    print ("yreturn :"..yreturn)
end)
coroutine.resume(coco,0,1)
coroutine.resume(coco,21)

--[[
    resume args:0,1
    yreturn :21
]]

例2:wrap使用

coco2 = coroutine.wrap(function (a,b)
    print("resume args:"..a..","..b)
    yreturn = coroutine.yield()
    print ("yreturn :"..yreturn)
end)
print(type(coco2))
coco2(0,1)
coco2(21)

--[[
    function
    resume args:0,1
    yreturn :21
]]--

例3:coroutine.status()协程的状态

function status()
    print("co1's status :"..coroutine.status(co1).." ,co2's status: "..coroutine.status(co2))
end

co1 = coroutine.create(function ( a )
    print("arg is :"..a)
    status()
    local stat,rere = coroutine.resume(co2,"2")
    print("resume's return is "..rere)
    status()
    local stat2,rere2 = coroutine.resume(co2,"4")
    print("resume's return is "..rere2)
    local arg = coroutine.yield("6")
end)
co2 = coroutine.create(function ( a )
    print("arg is :"..a)
    status()
    local rey = coroutine.yield("3")
    print("yeild's return is " .. rey)
    status()
    coroutine.yield("5")
end)
--主线程执行co1,传入字符串“main thread arg”
stat,mainre = coroutine.resume(co1,"1")
status()
print("last return is "..mainre)

例4:协程的运行过程

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"))

相关文章

  • Lua协程

    先看一段代码 运行结果at coAA -- 1at coBB -- 1at coBB -- 2at coCC --...

  • lua协程

    Lua中协同程序:意义和Unity中一样Lua中协同程序的函数被放在coroutine的表中协同程序状态:挂起、执...

  • Lua协程

    首先了解一下多线程。我们都知道线程——Thread。每一个线程都代表一个执行序列。当我们在程序中创建多线程的时候,...

  • SRS流媒体服务器源码分析(一):Rtmp publish流程

    线程模型 srs使用了state-threads协程库,是单线程多协程模型。这个协程的概念类似于lua的协程,都是...

  • (五)协程 Coroutine

    一、协程的概念 协作程序,解决异步问题 应用层完成调度 常见的支持协程的语言如: lua,C# 二、协程要解决什么...

  • 什么是Coroutines(协程)

    一、什么是Coroutines(协程) 协程是很久之前就提出的一个概念,目前支持协程的语言包括 lua、C#、go...

  • Python协程、yield、yield from

    前言 协程,又称微线程,纤程。英文名Coroutine。最近几年才在某些语言(如Lua)中得到广泛应用! 协程的特...

  • Lua-协程

    简介 示例 参数及返回值 create:返回coroutine,参数是函数 resume:返回bool值 yiel...

  • Lua 协程应用

    即使我死了,埋在土地里,我也要用我腐烂的声带喊出:闲置CPU是可耻。——孔子 进程,线程?并行,并发? 由于单核C...

  • Goroutine 随笔

    很早之前在lua中实现过一版协程,lua的栈是虚拟的,当要切换协程时虚拟栈不需要退栈,只需要从C的栈(物理栈)退出...

网友评论

      本文标题:Lua协程

      本文链接:https://www.haomeiwen.com/subject/onjvwktx.html