什么是协同(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. 谷歌分析(GA)新版的有哪些改变

    http://www.wocaoseo.com/thread-221-1-1.html 最近GA做了两次大规模改版,修改了GA使用率最高的traffic source.content面板以及最核心的a ...

  2. Kubernetes实战总结 - 阿里云ECS自建K8S集群

    一.概述 详情参考阿里云说明:https://help.aliyun.com/document_detail/98886.html?spm=a2c4g.11186623.6.1078.323b1c9b ...

  3. ARM开发板实现双系统引导的一种方法——基于迅为iTOP-4412开发板

    前言 本文所用的uboot代码为迅为官方提供,开发板是迅为iTOP-4412开发板.本文如有错误,欢迎指正. 首先,我们确定一下系统启动的流程:首先启动uboot,uboot启动内核并挂载rootfs ...

  4. django学习(二)

    1.反向解析 什么是方向解析呢? 通过一些方法得到一个结果,该结果可以直接访问对应url出发视图函数. 先给一个路由和视图函数起一个别名.但是我们要注意的是反向解析的别名是不可以冲突的!!!不然会出现 ...

  5. 深入了解Netty【五】线程模型

    引言 不同的线程模型对程序的性能有很大的影响,Netty是建立在Reactor模型的基础上,要搞清Netty的线程模型,需要了解一目前常见线程模型的一些概念. 具体是进程还是线程,是和平台或者编程语言 ...

  6. js+canvas画随机4位验证码

    啥都不说了,复制代码吧!!! <!DOCTYPE html> <html lang="en"> <head> <meta charset= ...

  7. Activiti7 启动流程实例

    package com.itheima.activiti; import org.activiti.engine.ProcessEngine; import org.activiti.engine.P ...

  8. python应用 处理excel数据

    实现功能 excel表格中有4列数,分别为RMF计算得到的 β,γ,势能面及组态,需要挑选出相同 β 值下势能面最低时的组态.为了减小数据量,先将 β 值保留两位小数. 代码 import xlrd ...

  9. Keepalived之高可用LVS集群

    前文我们聊了下keepalived的邮件通知相关配置,回顾请参考https://www.cnblogs.com/qiuhom-1874/p/13645163.html:今天我们来说说keepalive ...

  10. 【原创】Kuberneters-HelmV3.3.1入门介绍及实践

    一.为什么需要Helm? Kubernetes目前已成为容器编排的事实标准,随着传统架构向微服务容器化架构的转变,从一个巨大的单体的应用切分为多个微服务,每个微服务可独立部署和扩展,实现了敏捷开发和快 ...