【Lua学习笔记】Lua进阶——协程
文章目录
- 协程
- 协程的定义和调度
- Status
- Running
协程
协程是一种并发操作,相比于线程,线程在执行时往往是并行的,并且线程在创建销毁执行时极其消耗资源,并且过长的执行时间会造成主进程阻塞。而协程可以以并发时轮值时间片来执行,优点是不会阻塞,消耗资源少,可以手动控制。至于协程和线程的区别,什么是并发并行,请自行查阅或者学习操作系统理论知识。
协程的定义和调度
在Unity中,由于游戏是单线程的(这是为了其他线程不阻塞进程),因此我们常常需要使用协程。在Lua中也支持协程,例如下列代码:
Corou1 =coroutine.create(function ()print("我是协程1")
end)
print(Corou1)
Corou2 = coroutine.wrap(function ()print("我是协程2")
end)
print(Corou2)
coroutine.resume(Corou1) --开始或继续协程
Corou2() --运行函数
输出:
thread: 00CAEC00
function: 00CA0578
我是协程1
我是协程2
我们可以用两种不同的方法创建协程,不过返回值一个是协程(虽然thread是线程),一个是函数。所以对这两个协程的运行方式也不同。如何理解这两种方式?我想用C#的例子:
void StartCorou() --function类型
{StartCoroutine(Coroutine()); --thread类型直接执行
}IEnumerator Coroutine()
{
}
thread类型定义的就是协程本身,因此我们可以用lua提供的协程table中的方法来调用,而function类型更像是定义了一个启动函数,通过调用这个函数来执行。
在Lua中的协程有一个优点:我们可以手动执行
Corou1 =coroutine.create(function ()local i = 1while true doprint(i)i = i + 1coroutine.yield(i) --yield也可以返回end
end)coroutine.resume(Corou1)
a,b = coroutine.resume(Corou1)
print(a,b)
coroutine.resume(Corou1)输出:
1
2
true 3
3 通过注释我们可以发现,resume第一个返回固定为成功判断,然后返回yield提供的变长参数
function coroutine.resume(co: thread, val1?: any, ...any)-> success: boolean2. ...any
可以看到,对于进入了yield的协程,需要我们手动执行resume才能继续执行。而非自动地轮换时间片。这样有利有弊,但我认为在调度上更加灵活了。
使用wrap的话:
function f1()local i = 1while true doprint(i)i = i + 1coroutine.yield(i) end
end
b = coroutine.wrap(f1)
print("返回值"..b())
print("返回值"..b())
print("返回值"..b())输出:
1
返回值2
2
返回值3
3
返回值4function coroutine.wrap(f: fun(...any):...unknown)-> fun(...any):...unknown
使用wrap则我们发现,wrap并不返回成功判断,而是直接返回yield给出的变长参数,这是由于其内定义的函数就只接收变长参数。
Status
Lua中的协程总共有四种状态:
function coroutine.status(co: thread)-> "dead"|"normal"|"running"|"suspended"
以字符串形式返回协程 co 的状态。return #1:| "running" 正在运行。| "suspended" 挂起或是还没有开始运行。| "normal" 是活动的,但并不在运行。| "dead" 运行完主体函数或因错误停止。
让我们从下面的例子看看协程什么时候会进入这些状态:
C2 = coroutine.create(function ()print("协程2执行")print("此时协程1:"..coroutine.status(Corou1))coroutine.yield()
end)
Corou1 =coroutine.create(function ()local i = 1while i<3 doprint(i)i = i + 1if i==2 thencoroutine.resume(C2)endprint(coroutine.status(Corou1))coroutine.yield() end
end)
print(coroutine.status(Corou1))
print("######")
coroutine.resume(Corou1)
print(coroutine.status(Corou1))
print("######")
coroutine.resume(Corou1)
print(coroutine.status(Corou1))
print("######")
coroutine.resume(Corou1)
print(coroutine.status(Corou1))
print("######")输出:
suspended
######
1
协程2执行
此时协程1:normal
running
suspended
######
2
running
suspended
######
dead
######
从上述例子中看到,当协程未启动以及暂停中等待下一次resume时,其状态是suspended。而当协程正在执行时状态是running,当协程1执行切换到协程2时,协程1的状态是normal。最后当协程1退出时其状态是dead。
Running
running函数可以得到当前正在运行的协程(的地址)。
function coroutine.running()-> running: thread2. ismain: boolean
返回当前正在运行的协程加一个布尔量。 如果当前运行的协程是主线程,其为真。
(我试了一下没接收到这个bool,不知道什么情况)
用例:
Corou1 =coroutine.create(function ()local i = 1while i<3 doprint(i)i = i + 1print("协程1状态:"..coroutine.status(Corou1))print(coroutine.running())coroutine.yield() end
end)
coroutine.resume(Corou1)输出:
1
协程1状态:running
thread: 00A7E1F8 <-- 协程1的地址
先抛出一个问题:如果在上述的同样代码中,执行协程2时print这个running函数,请问可以得到什么?考虑到协程1在协程2运行时是normal状态,当前运行(running)的协程应当是协程2
C2 = coroutine.create(function ()print("协程2执行")print(coroutine.running())print("此时协程1:" .. coroutine.status(Corou1))print("协程2执行结束")coroutine.yield()
end)
Corou1 =coroutine.create(function ()local i = 1while i<3 doprint(i)i = i + 1if i==2 thencoroutine.resume(C2)endprint("协程1状态:"..coroutine.status(Corou1))print(coroutine.running())coroutine.yield() end
end)
coroutine.resume(Corou1)
coroutine.resume(Corou1)输出:
1
协程2执行
thread: 00C4CFE8
此时协程1:normal
协程2执行结束
协程1状态:running
thread: 00C4D408
2
协程1状态:running
thread: 00C4D408
相关文章:

【Lua学习笔记】Lua进阶——协程
文章目录 协程协程的定义和调度StatusRunning 协程 协程是一种并发操作,相比于线程,线程在执行时往往是并行的,并且线程在创建销毁执行时极其消耗资源,并且过长的执行时间会造成主进程阻塞。而协程可以以并发时轮值时间片来执行&…...

亚马逊云科技纽约峰会,充分释放数据价值和生成式AI的潜力
生成式AI将深刻改变每个公司的运营方式,标志着人工智能技术发展的新转折点。亚马逊云科技昨日在纽约峰会上宣布,推出七项生成式AI新功能,进一步降低了生成式AI的使用门槛,让无论是业务用户还是开发者都能从中受益。借助这些新功能…...

什么是 web3?
在百度搜索引擎输入 “Web3”、“大厂”。跳出来基本都是这样的标题. 以及如今的互联网行业 “哀鸿遍野”,不仅内卷,还裁员。然后掀起一阵风,猛吹 Web3 的好,数据回归用户……最后再 “威逼利诱” 一下,Web3 就是 20 年…...

[驱动开发]字符设备驱动应用——点灯
点亮开发板stm32mp157的三盏灯 //头文件 #ifndef __LED_H__ #define __LED_H__//封装GPIO寄存器 typedef struct { volatile unsigned int MODER; // 0x00volatile unsigned int OTYPER; // 0x04volatile unsign…...

前端学习——Vue (Day5)
自定义指令 <template><div><h1>自定义指令</h1><input v-focus ref"inp" type"text" /></div> </template><script> export default {// mounted(){// this.$ref.inp.focus()// }// 2. 局部注册指令di…...

Ceph版本
每个Ceph的版本都有一个英文的名称和一个数字形式的版本编号 第一个 Ceph 版本编号是 0.1,发布于2008 年 1月。之后是0.2,0.3....多年来,版本号方案一直没变。 2015年 4月0.94.1 (Hammer 的第一个修正版) 发布后,为了避免 0.99 (以及 0.100…...

cspm是什么?考了有用吗?
CSPM是项目管理专业人员能力评价等级证书,相当于 PMP 的本土化,CSPM 相关问题大家都很关心,今天就给大家全面解答一下 CSPM到底是何方神圣? 文章主要是解答下面几个常见问题,其他问题可以留言或者私信咨询我哦~ 一、什…...

Java阶段五Day14
Java阶段五Day14 文章目录 Java阶段五Day14分布式事务整合demo案例中架构,代码关系发送半消息本地事务完成检查补偿购物车消费 鲁班周边环境调整前端启动介绍启动前端 直接启动的项目gateway(网关)login(登录注册)atta…...

【计算机网络】应用层协议 -- 安全的HTTPS协议
文章目录 1. 认识HTTPS2. 使用HTTPS加密的必要性3. 常见的加密方式3.1 对称加密3.2 非对称加密3.3 非对称加密对称加密 4. 引入CA证书4.1 CA认证4.2 数据签名4.3 非对称机密对称加密证书认证4.4 常见问题 5. 总结 1. 认识HTTPS HTTPS全称为 Hyper Text Tranfer Protocol over …...

小程序通过ip+port+路径获取服务器中的图片
配置IIS 首先需要配置IIS。 打开控制面板,接下来的流程按下图所示。 安装好后,按“win”键,搜索IIS 选择一个ip地址,或手动填写,端口号按需更改...
Codeforces Round 888 (Div. 3)(A-F)
文章目录 ABCDEF A 题意: 就是有一个m步的楼梯。每一层都有k厘米高,现在A的身高是H,给了你n个人的身高问有多少个人与A站在不同层的楼梯高度相同。 思路: 我们只需要去枚举对于A来说每一层和他一样高(人的身高和楼…...
【人工智能】深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化
深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化) 文章目录 深度神经网络、卷积神经网络(CNN)、多卷积核、全连接、池化)深度神经网络训练训练深度神经网络参数共享卷积神经网络(CNN)卷积多卷积核卷积全连接最大池化卷积+池化拉平向量激活函数优化小结深度神经…...

失去SSL证书,会对网站安全造成什么影响?
作为网络世界中的“身份证”,SSL证书可以在网络世界中证明你是一个真实可信的企业或个人网站,而不是一个钓鱼网站。且在网站的服务器上部署SSL证书后,可以使网站与访问者之间通过SSL协议建立安全的加密连接,确保在Web服务器和浏览…...

gitee中fork了其他仓库,如何在本地进行同步
GitHub 操作:同步 Fork 来的仓库(上游仓库)_sigmarising的博客-CSDN博客 1. 设置upstream 2. git pull --rebase 3. 然后再执行pull、push操作...

java项目之社区生活超市管理系统(ssm+mysql+jsp)
风定落花生,歌声逐流水,大家好我是风歌,混迹在java圈的辛苦码农。今天要和大家聊的是一款基于ssm的社区生活超市管理系统。技术交流和部署相关看文章末尾! 开发环境: 后端: 开发语言:Java 框…...
WebGPU(七):C++头部封装
WebGPU(七):C头部封装 在前面的学习中,我们使用的都是原生态的WebGPU API,那是基于C语言的API,但是为了更高效的开发,我们可以使用一个基于C的库。 根据参考的教程,这个github库提供更加纤细的描述。它提…...

Linux 网络通信epoll详解( 10 ) -【Linux通信架构系列 】
系列文章目录 C技能系列 Linux通信架构系列 C高性能优化编程系列 深入理解软件架构设计系列 高级C并发线程编程 期待你的关注哦!!! 现在的一切都是为将来的梦想编织翅膀,让梦想在现实中展翅高飞。 Now everything is for the…...
java源码-List源码解析
Java中的List是一个接口,它定义了一组操作列表的方法。List接口的常见子类包括ArrayList、LinkedList和Vector等。 以下是Java中List接口及其常见方法的源码解析: 1. List接口定义 public interface List<E> extends Collection<E> { …...
Mybatis的动态SQL
动态 sql 是Mybatis的强⼤特性之⼀,能够完成动态的 sql 语句拼接。 动态 SQL 大大减少了编写代码的工作量,更体现了 MyBatis 的灵活性、高度可配置性和可维护性。 Mybatis里的动态标签主要有: <if><trim><where><set><forea…...

嵌入式系统中的GPIO控制:从理论到实践与高级应用
本文将探讨嵌入式系统中的GPIO(通用输入输出)控制,着重介绍GPIO的原理和基本用法。我们将使用一个实际的示例项目来演示如何通过编程配置和控制GPIO引脚。将基于ARM Cortex-M微控制器,并使用C语言进行编写。 GPIO是嵌入式系统中最常见且功能最强大的接口之一。它允许硬件工…...

wordpress后台更新后 前端没变化的解决方法
使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...
Python爬虫实战:研究MechanicalSoup库相关技术
一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

从深圳崛起的“机器之眼”:赴港乐动机器人的万亿赛道赶考路
进入2025年以来,尽管围绕人形机器人、具身智能等机器人赛道的质疑声不断,但全球市场热度依然高涨,入局者持续增加。 以国内市场为例,天眼查专业版数据显示,截至5月底,我国现存在业、存续状态的机器人相关企…...
C++.OpenGL (10/64)基础光照(Basic Lighting)
基础光照(Basic Lighting) 冯氏光照模型(Phong Lighting Model) #mermaid-svg-GLdskXwWINxNGHso {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-GLdskXwWINxNGHso .error-icon{fill:#552222;}#mermaid-svg-GLd…...

NLP学习路线图(二十三):长短期记忆网络(LSTM)
在自然语言处理(NLP)领域,我们时刻面临着处理序列数据的核心挑战。无论是理解句子的结构、分析文本的情感,还是实现语言的翻译,都需要模型能够捕捉词语之间依时序产生的复杂依赖关系。传统的神经网络结构在处理这种序列依赖时显得力不从心,而循环神经网络(RNN) 曾被视为…...
Java线上CPU飙高问题排查全指南
一、引言 在Java应用的线上运行环境中,CPU飙高是一个常见且棘手的性能问题。当系统出现CPU飙高时,通常会导致应用响应缓慢,甚至服务不可用,严重影响用户体验和业务运行。因此,掌握一套科学有效的CPU飙高问题排查方法&…...
Python 包管理器 uv 介绍
Python 包管理器 uv 全面介绍 uv 是由 Astral(热门工具 Ruff 的开发者)推出的下一代高性能 Python 包管理器和构建工具,用 Rust 编写。它旨在解决传统工具(如 pip、virtualenv、pip-tools)的性能瓶颈,同时…...
【Java学习笔记】BigInteger 和 BigDecimal 类
BigInteger 和 BigDecimal 类 二者共有的常见方法 方法功能add加subtract减multiply乘divide除 注意点:传参类型必须是类对象 一、BigInteger 1. 作用:适合保存比较大的整型数 2. 使用说明 创建BigInteger对象 传入字符串 3. 代码示例 import j…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...

Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...