lua基础之协程
创始人
2024-02-04 09:00:33
0

简介

协程是一种非常强大的方法,可以将函数的执行拆分直到发生某些事件(例如,计时器触发或输入到达)。 该函数选择何时“屈服”执行。
yield / resume 序列允许变量在线程和调用者之间来回传递。 例如,线程可以用一个参数让出,告诉调用者它为什么让出,而调用者可以用一个参数恢复,告诉线程它为什么被恢复。

线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。
在任一指定时刻只有一个协同程序在运行,并且这个正在运行的协同程序只有在明确的被要求挂起的时候才会被挂起。
协同程序有点类似同步的多线程,在等待同一个线程锁的几个线程有点类似协同。

coroutine.create()

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

coroutine.resume()

重启 coroutine,和 create 配合使用

coroutine.running()

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

coroutine.status()

查看 coroutine 的状态
coroutine 的状态有三种:dead,suspended,running

coroutine.wrap()

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

coroutine.yield()

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

样例1

co = coroutine.create(function(i)print(i);end
)coroutine.resume(co, 1)   -- 1
print(coroutine.status(co))  -- deadprint("----------")co = coroutine.wrap(function(i)print(i);end
)co(1)print("----------")co2 = coroutine.create(function()for i=1,10 doprint(i)if i == 3 thenprint(coroutine.status(co2))  --runningprint(coroutine.running()) --thread:XXXXXXendcoroutine.yield()endend
)coroutine.resume(co2) --1
coroutine.resume(co2) --2
coroutine.resume(co2) --3print(coroutine.status(co2))   -- suspended
print(coroutine.running())print("----------")

Output

1
dead
----------
1
----------
1
2
3
running
thread: 0x7fb801c05868    false
suspended
thread: 0x7fb801c04c88    true
----------

样例2

function foo (a)print("foo 函数输出", a)return coroutine.yield(2 * a) -- 返回  2*a 的值
endco = coroutine.create(function (a , b)print("第一次协同程序执行输出", a, b) -- co-body 1 10local 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("---分割线---")

output

第一次协同程序执行输出    1    10
foo 函数输出    2
main    true    4
--分割线----
第二次协同程序执行输出    r
main    true    11    -9
---分割线---
第三次协同程序执行输出    x    y
main    true    10    结束协同程序
---分割线---
main    false    cannot resume dead coroutine
---分割线---

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

生产者-消费者问题

local newProductorfunction productor()local i = 0while true doi = i + 1send(i)     -- 将生产的物品发送给消费者end
endfunction consumer()while true dolocal i = receive()     -- 从生产者那里得到物品print(i)end
endfunction receive()local status, value = coroutine.resume(newProductor)return value
endfunction send(x)coroutine.yield(x)     -- x表示需要发送的值,值返回以后,就挂起该协同程序
end-- 启动程序
newProductor = coroutine.create(productor)
consumer()

Output

1
2
3
4
5
6
7
8
9
10
11
12
13
……

相关内容

热门资讯

AWSECS:访问外部网络时出... 如果您在AWS ECS中部署了应用程序,并且该应用程序需要访问外部网络,但是无法正常访问,可能是因为...
AWSElasticBeans... 在Dockerfile中手动配置nginx反向代理。例如,在Dockerfile中添加以下代码:FR...
银河麒麟V10SP1高级服务器... 银河麒麟高级服务器操作系统简介: 银河麒麟高级服务器操作系统V10是针对企业级关键业务...
北信源内网安全管理卸载 北信源内网安全管理是一款网络安全管理软件,主要用于保护内网安全。在日常使用过程中,卸载该软件是一种常...
AWR报告解读 WORKLOAD REPOSITORY PDB report (PDB snapshots) AW...
AWS管理控制台菜单和权限 要在AWS管理控制台中创建菜单和权限,您可以使用AWS Identity and Access Ma...
​ToDesk 远程工具安装及... 目录 前言 ToDesk 优势 ToDesk 下载安装 ToDesk 功能展示 文件传输 设备链接 ...
群晖外网访问终极解决方法:IP... 写在前面的话 受够了群晖的quickconnet的小水管了,急需一个新的解决方法&#x...
不能访问光猫的的管理页面 光猫是现代家庭宽带网络的重要组成部分,它可以提供高速稳定的网络连接。但是,有时候我们会遇到不能访问光...
Azure构建流程(Power... 这可能是由于配置错误导致的问题。请检查构建流程任务中的“发布构建制品”步骤,确保正确配置了“Arti...