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

  什么是协同(coroutine)?

  Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。

  协同是非常强大的功能,但是用起来也很复杂。

  线程和协同程序区别

  线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。

  在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。

  协同程序有点类似同步的多线程,在等待同一个线程锁的几个线程有点类似协同。

  基本语法

  方法描述

  coroutine.create()创建coroutine,返回coroutine, 参数是一个函数,当和resume配合使用的时候就唤醒函数调用

  coroutine.resume()重启coroutine,和create配合使用

  coroutine.yield()挂起coroutine,将coroutine设置为挂起状态,这个和resume配合使用能有很多有用的效果

  coroutine.status()查看coroutine的状态

  注:coroutine的状态有三种:dead,suspend,running,具体什么时候有这样的状态请参考下面的程序

  coroutine.wrap()创建coroutine,返回一个函数,一旦你调用这个函数,就进入coroutine,和create功能重复

  coroutine.running()返回正在跑的coroutine,一个coroutine就是一个线程,当使用running的时候,就是返回一个corouting的线程号

  以下实例演示了以上各个方法的用法:

  -- coroutine_test.lua 文件

  co = coroutine.create(

  function(i)

  print(i);

  end

  )

  coroutine.resume(co, 1) -- 1

  print(coroutine.status(co)) -- dead

  print("----------")

  co = coroutine.wrap(

  function(i)

  print(i);

  end

  )

  co(1)

  print("----------")

  co2 = coroutine.create(

  function()

  for i=1,10 do

  print(i)

  if i == 3 then

  print(coroutine.status(co2)) --running

  print(coroutine.running()) --thread:XXXXXX

  end

  coroutine.yield()

  end

  end

  )

  coroutine.resume(co2) --1

  coroutine.resume(co2) --2

  coroutine.resume(co2) --3

  print(coroutine.status(co2)) -- suspended

  print(coroutine.running())

  print("----------")

  以上实例执行输出结果为:

  1

  dead

  ----------

  1

  ----------

  1

  2

  3

  running

  thread: 0x7fb801c05868 false

  suspended

  thread: 0x7fb801c04c88 true

  ----------

  coroutine.running就可以看出来,coroutine在底层实现就是一个线程。

  当create一个coroutine的时候就是在新线程中注册了一个事件。

  当使用resume触发事件的时候,create的coroutine函数就被执行了,当遇到yield的时候就代表挂起当前线程,等候再次resume触发事件。

  接下来我们分析一个更详细的实例:

  function foo (a)

  print("foo 函数输出", a)

  return coroutine.yield(2 * a) -- 返回 2*a 的值

  end

  co = coroutine.create(function (a , b)

  print("第一次协同程序执行输出", a, b) -- co-body 1 10

  local r = foo(a + 1)

  print("第二次协同程序执行输出", r)

  local r, s = coroutine.yield(a + b, a - b) -- a,b的值为第一次调用协同程序时传入

  print("第三次协同程序执行输出", r, s)

  return b, "结束协同程序" -- b的值为第二次调用协同程序时传入

  end)

  print("main", coroutine.resume(co, 1, 10)) -- true, 4

  print("--分割线----")

  print("main", coroutine.resume(co, "r")) -- true 11 -9

  print("---分割线---")

  print("main", coroutine.resume(co, "x", "y")) -- true 10 end

  print("---分割线---")

  print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine

  print("---分割线---")

  以上实例执行输出结果为:

  第一次协同程序执行输出 1 10

  foo 函数输出 2

  main true 4

  --分割线----

  第二次协同程序执行输出 r

  main true 11 -9

  ---分割线---

  第三次协同程序执行输出 x y

  main true 10 结束协同程序

  ---分割线---

  main false cannot resume dead coroutine

  ---分割线---

  以上实例接下如下:

  调用resume,将协同程序唤醒,resume操作成功返回true,否则返回false;

  协同程序运行;

  运行到yield语句;

  yield挂起协同程序,第一次resume返回;(注意:此处yield返回,参数是resume的参数)

  第二次resume,再次唤醒协同程序;(注意:此处resume的参数中,除了第一个参数,剩下的参数将作为yield的参数)

  yield返回;

  协同程序继续运行;

  如果使用的协同程序继续运行完成后继续调用 resume方法则输出:cannot resume dead coroutine

  resume和yield的配合强大之处在于,resume处于主程中,它将外部状态(数据)传入到协同程序内部;而yield则将内部的状态(数据)返回到主程中。

  生产者-消费者问题

  现在我就使用Lua的协同程序来完成生产者-消费者这一经典问题。

  local newProductor

  function productor()

  local i = 0

  while true do

  i = i + 1

  send(i) -- 将生产的物品发送给消费者

  end

  end

  function consumer()

  while true do

  local i = receive() -- 从生产者那里得到物品

  print(i)

  end

  end

  function receive()

  local status, value = coroutine.resume(newProductor)

  return value

  end

  function send(x)

  coroutine.yield(x) -- x表示需要发送的值,值返回以后,就挂起该协同程序

  end

  -- 启动程序

  newProductor = coroutine.create(productor)

  consumer()

  以上实例执行输出结果为:

  1

  2

  3

  4

  5

  6

  7

  8

  9

  10

  11

  12

  13

  ……

  (编辑:雷林鹏 来源:网络 侵删)

原文地址:https://www.cnblogs.com/pengpeng1208/p/11132010.html

时间: 2024-08-29 18:17:57

雷林鹏分享:Lua 协同程序(coroutine)的相关文章

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

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

Lua之协同程序(coroutine)

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

Lua中的协同程序 coroutine

Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时刻只能有一个协程在运行.并且Lua中的协程无法在外部将其停止,而且有可能导致程序阻塞. 协同程序(Coroutine): 三个状态:suspended(挂起,协同刚创建完成时或者yield之后).running(运行).dead(函数走完后的状态,这时候不能再重新resume). coroutine

Lua中的协同程序 coroutine(转)

Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时刻只能有一个协程在运行.并且Lua中的协程无法在外部将其停止,而且有可能导致程序阻塞. 协同程序(Coroutine): 三个状态:suspended(挂起,协同刚创建完成时或者yield之后).running(运行).dead(函数走完后的状态,这时候不能再重新resume). coroutine

雷林鹏分享:XML 应用程序

XML 应用程序 本章演示一些基于 XML, HTML, XML DOM 和 JavaScript 构建的小型 XML 应用程序. XML 文档实例 在本应用程序中,我们将使用 "cd_catalog.xml" 文件. 在 HTML div 元素中显示第一个 CD 下面的实例从第一个 CD 元素中获取 XML 数据,然后在 id="showCD" 的 HTML 元素中显示数据.displayCD() 函数在页面加载时调用: 实例 x=xmlDoc.getElemen

雷林鹏分享:Lua 迭代器

迭代器(iterator)是一种对象,它能够用来遍历标准模板库容器中的部分或全部元素,每个迭代器对象代表容器中的确定的地址 在Lua中迭代器是一种支持指针类型的结构,它可以遍历集合的每一个元素. 泛型 for 迭代器 泛型 for 在自己内部保存迭代函数,实际上它保存三个值:迭代函数.状态常量.控制变量. 泛型 for 迭代器提供了集合的 key/value 对,语法格式如下: for k, v in pairs(t) do print(k, v) end 上面代码中,k, v为变量列表;pai

雷林鹏分享:Lua 模块与包

模块类似于一个封装库,从 Lua 5.1 开始,Lua 加入了标准的模块管理机制,可以把一些公用的代码放在一个文件里,以 API 接口的形式在其他地方调用,有利于代码的重用和降低代码耦合度. Lua 的模块是由变量.函数等已知元素组成的 table,因此创建一个模块很简单,就是创建一个 table,然后把需要导出的常量.函数放入其中,最后返回这个 table 就行.以下为创建自定义模块 module.lua,文件代码格式如下: -- 文件名为 module.lua -- 定义一个名为 modul

雷林鹏分享:Flask应用程序

要测试Flask安装是否成功,在编辑器中输入以下代码,并保存到文件:Hello.py 中. from flask import Flask app = Flask(__name__) @app.route('/') def hello_world(): return 'Hello World' if __name__ == '__main__': app.run() 在项目中导入Flask模块是强制性的. Flask类的一个对象是WSGI应用程序. Flask构造函数将当前模块的名称(__nam

四、Lua协同程序

一.协同程序基础 1.什么是协同程序 协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和指令指针(即可以保存变量的值和状态),同时又与其他协同程序共享全局变量和其他大部分东西. 与线程的区别是具有多个线程的程序可以同时运行几个线程,而程序任意时刻只能运行一个协同程序,并且协同程序只有被显示地(执行挂起函数)要求挂起才会暂停. 2.四种状态 (1)挂起(suspended):创建时或执行了操作coroutine.yield() (2)运行(running):执行了corouti