四、Lua协同程序

一、协同程序基础

1.什么是协同程序

  协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针(即可以保存变量的值和状态),同时又与其他协同程序共享全局变量和其他大部分东西。

  与线程的区别是具有多个线程的程序可以同时运行几个线程,而程序任意时刻只能运行一个协同程序,并且协同程序只有被显示地(执行挂起函数)要求挂起才会暂停。

2.四种状态

  (1)挂起(suspended):创建时或执行了操作coroutine.yield()

  (2)运行(running):执行了coroutine.resume()

  (3)死亡(dead):最后一次调用resume时,协同程序的内容已执行完毕,并且已经返回。resume状态为dead的协同程序将返回false及错误消息,不再执行主函数体。

  (4)正常(normal):当一个协同程序A唤醒另一个协同程序B时,A就处于一种特殊状态——既不是挂机状态(A不能继续执行),也不是运行状态(B在运行)。

3.相关函数(都存放在全局table coroutine中)

  (1)create(fun):用于创建协同程序,只有一个参数,就是一个函数(一般为匿名函数),函数中的代码就是协同程序将要执行的内容。create返回值的类型为thread。创建后的协同程序处于挂起状态。

  (2)resume(co,...):启动或再次启动协同程序。参数列表中:co表示将要被启动的协同程序,后面为变长的可选参数。

  (3)yield(...):使正在运行的协同程序挂起,之后可以再恢复运行(调用resume)。只能被协同程序的主函数调用(即在协同程序执行的内容中调用)。参数列表为可选的变长参数。

  (4)status(co):检查协同程序的当前状态,返回值为四中状态中的一种。参数co为待检查的协同程序。

4.有用机制:通过一对resume-yield交换数据

  原理:

  (1)所有传递给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

              i = i+1  --有语法错误

            end )          

          第一次调用resume:print(coroutine.resume(co,20,10)) -->true  30  10   --第一个返回值为true表示协同程序执行完毕或执行到yield之前没有发生错误,后面的返回值就是传递给yield的参数。 

          第二次调用resume:print(coroutine.resume(co,20,10)) -->false,attempt to perform arithmetic on global ‘i‘ (a nil value) --resume 第一个返回值为true并不能说明协同程序没有错误。

  (3)yield的返回值就是对应resume传入的额外参数。如:

          co = coroutine.create( function() print("co:",coroutine.yield()) end)

          coroutine.resume(co) -->   --resume中没有额外参数,则yield不会返回值,协同程序挂起

  (4)当协同程序结束时,它的主函数返回的值都将作为resume的返回值。如:

          co = coroutine.create( function() return 1,2 end )

          print(coroutine.resume(co)) -->true 1  2

二、协同程序的应用

1.生产者-消费者

  (1)生产者-消费者一般程序表示:

      function producer() --生产者                                    function consumer() --消费者

        while true do                     while true do   

          local x = io.read()                  local x = receive()

          send(x)                       io.write(x,"\n")

        end                           end

      end                          end

      问题关键:如何将send和receive匹配起来?

  (2)生产者-消费者协同程序实现   

      function send(x) --协同程序主函数中被调用,因而可以调用yield
        coroutine.yield(x) --参数x将作为resume的返回值
      end

      producer = coroutine.create( function()  --在这里可以理解为生产者
            while true do
              local x = io.read() --输入,这里可理解为生产的东西
              send(x)
            end
          end)

      function receive()  --在这里可以理解为消费者
        local status, value = coroutine.resume(producer) --启动协同程序
        return value
      end

      程序通过调用消费者receive()来唤醒生产者(即协同程序),然后通过将“生产的”内容x作为参数传递给yield,最后作为resume的返回值,赋给value(即消费者得到生产者生产的东西)

      实质上利用了一对resume-yield交换数据。

时间: 2024-10-23 16:33:02

四、Lua协同程序的相关文章

雷林鹏分享:Lua 协同程序(coroutine)

什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西. 协同是非常强大的功能,但是用起来也很复杂. 线程和协同程序区别 线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行. 在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起. 协同程序有点类似同步的多线程,在

Lua 学习之基础篇九<Lua 协同程序(Coroutine)>

引言 讲到协程,首先来介绍一下线程和协程的区别 lua协程和多线程 相同之处:拥有自己独立的桟.局部变量和PC计数器,同时又与其他协程共享全局变量和其他大部分东西 不同之处:一个多线程程序可以同时运行几个线程(并发执行.抢占),而协程却需要彼此协作地运行,并非真正的多线程,即一个多协程程序在同一时间只能运行一个协程,并且正在执行的协程只会在其显式地要求挂起(suspend)时,它的执行才会暂停(无抢占.无并发). 注意: Lua中的协程无法在外部将其停止,有可能导致程序阻塞 运行的是主线程时调用

Lua之协同程序(coroutine)

什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西. 协同是非常强大的功能,但是用起来也很复杂. 线程和协同程序区别 线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行. 在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起. 协同程序有点类似同步的多线程,在

Lua语言基础汇总(7) -- 协同程序

前言 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.从概念上讲,线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行.就是说,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显式地要求挂起时,它的执行才会暂停. 协同程序基础 Lua将所有关于协同程序的函数放置在一个名为“coroutine”的table中.函数create

Lua中的协同程序

[前言] 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.从概念上讲,线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行.就是说,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显式地要求挂起时,它的执行才会暂停. [协同程序基础] Lua将所有关于协同程序的函数放置在一个名为"coroutine"的table中

lua程序设计之协同程序

本文的内容主要来自于<lua程序设计>一书,部分内容来自网络 一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显式地要求挂起时,它的执行才会暂停. 一 协同程序基础 -协同程序的函数放在"coroutine"的table中 -状态status -suspended 初始状态(创建时) -running -    dead -normal:当协程A唤醒协程B,A就处于normal状态 -coroutine函数 -coroutine.cr

[转]Lua语言基础汇总(7) -- 协同程序

前言 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针,同时又与其它协同程序共享全局变量和其它大部分东西.从概念上讲,线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行.就是说,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显式地要求挂起时,它的执行才会暂停. 协同程序基础 Lua将所有关于协同程序的函数放置在一个名为“coroutine”的table中.函数create

【笨木头Lua专栏】基础补充07:协同程序初探

哎.周五晚上我都还这么努力看书.真是好孩子.(小若:不想吐槽了) 事实上我都准备rs=1&u=http%3A%2F%2Fwww%2Ebenmutou%2Ecom%2Farchives%2F1733&p=baidu&c=news&n=10&t=tpclicked3_hc&q=25013069_cpr&k=%CD%E6%D3%CE%CF%B7&k0=%B4%F2%D3%A1&kdi0=1&k1=%D7%C0%D7%D3&k

Lua学习笔记之协同程序

1.  协同程序与多线程情况下的线程比较类似,有自己的堆栈.自己的局部变量,有自己的指令指针,但是和其他协同程序共享全局变量等很多信息.线程和协同程序的主要不同在于:在多核处理器情况下,多线程程序同时运行多个线程,而协同程序是通过协作来完成,在任意指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才被挂起. 2.  协同的基础 Lua通过table提供了所有的协同函数,create函数创建一个新的协同程序,create只有一个参数,协同程序将要运行的代码封装而