什么是协同(coroutine)?

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

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

线程和协同程序区别

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

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

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

基本语法

方法 描述

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

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

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

coroutine.status() 查看 coroutine 的状态

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

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

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

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

coroutine_test.lua 文件

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

……

Lua 协同程序(coroutine)的更多相关文章

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

    引言 讲到协程,首先来介绍一下线程和协程的区别 lua协程和多线程 相同之处:拥有自己独立的桟.局部变量和PC计数器,同时又与其他协程共享全局变量和其他大部分东西 不同之处:一个多线程程序可以同时运行 ...

  2. Lua中的协同程序 coroutine

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  3. Lua中的协同程序 coroutine(转)

    Lua中的协程和多线程很相似,每一个协程有自己的堆栈,自己的局部变量,可以通过yield-resume实现在协程间的切换.不同之处是:Lua协程是非抢占式的多线程,必须手动在不同的协程间切换,且同一时 ...

  4. 【转】关于Unity协同程序(Coroutine)的全面解析

    http://www.unity.5helpyou.com/2658.html 本篇文章我们学习下unity3d中协程Coroutine的的原理及使用 1.什么是协调程序 unity协程是一个能暂停执 ...

  5. lua 15 协程-协同程序

    转自:http://www.runoob.com/lua/lua-coroutine.html 什么是协同(coroutine)? Lua 协同程序(coroutine)与线程比较类似:拥有独立的堆栈 ...

  6. Lua学习笔记4. coroutine协同程序和文件I/O、错误处理

    Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...

  7. Lua 学习笔记(九)协同程序(线程thread)

    协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈.局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西.从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的 ...

  8. Unity 中的协同程序

    今天咱就说说,协同程序coroutine.(这文章是在网吧敲的,没有unity,但是所有结论都被跑过,不管你信得过我还是信不过我,都要自己跑一下看看,同时欢迎纠错)先说说啥是协程:协同程序是一个非常让 ...

  9. Unity3D协同程序(Coroutine)

    摘要下: 1. coroutine, 中文翻译"协程".这个概念可能有点冷门,不过百度之,说是一种很古老的编程模型了,以前的操作系统里进程调度里用到过,现在操作系统的进程调度都是根 ...

随机推荐

  1. IntelliJ IDEA下git版本回退,版本还原

    原文链接:https://blog.csdn.net/hehyyoulan/article/details/80005272

  2. oracle备份之恢复管理目录

    一.管理恢复目录 #现实应用中一般都是专门新建一个rman 数据库,给所有的数据库做catalog1.建立恢复目录 #建立恢复目录表空间SQL> create tablespace rman_t ...

  3. 【Flutter 实战】17篇动画系列文章带你走进自定义动画

    老孟导读:Flutter 动画系列文章分为三部分:基础原理和核心概念.系统动画组件.8篇自定义动画案例,共17篇. 动画核心概念 在开发App的过程中,自定义动画必不可少,Flutter 中想要自定义 ...

  4. P3419 [POI2005]SAM-Toy Cars

    Description ​ Jasio 是一个三岁的小男孩,他最喜欢玩玩具了,他有n 个不同的玩具,它们都被放在了很高的架子上所以Jasio 拿不到它们. 为了让他的房间有足够的空间,在任何时刻地板上 ...

  5. 面向嵌入式的JavaScript引擎

    https://jerryscript.net/ https://duktape.org/ https://github.com/ialex32x/duktape-unity https://gith ...

  6. python小白入门基础(三:整型)

    # Number(int float str complex) #int 整型(正整数 0 负整数)intvar_1 = 100print(intvar_1)invar_2 = 0 print(inv ...

  7. Java内存模型分析

    在学习Java内存模型之前,先了解一下线程通信机制. 1.线程通信机制 在并发编程中,线程之间相互交换信息就是线程通信.目前有两种机制:内存共享与消息传递. 1.1.共享内存 Java采用的就是共享内 ...

  8. 微服务实战SpringCloud之Spring Cloud Feign替代HTTP Client

    简介 在项目中我们有时候需要调用第三方的API,微服务架构中这种情况则更是无法避免--各个微服务之间通信.比如一般的项目中,有时候我们会使用 HTTP Client 发送 HTTP 请求来进行调用,而 ...

  9. JVM学习第二天(垃圾回收器和内存分配策略)大章

    说道垃圾回收器大家应该都会有所了解,GC白,当然说道具体的可能就不是很清楚了,今天我们就来玩一玩; GC要做的事情: 第一步:确定堆中需要回收的对象; 第二步:什么时候回收; 第三步:怎样回收 为什么 ...

  10. H5简单内容

    1.简单认识H5 HTML5不仅仅是作为HTML标记语言的一个最新版本,更重要的是它指定了Web开发的一系列标准,成为第一个将Web作为应用开发平台的HTML语言. 我们日常讨论的H5其实是有一个泛称 ...