Lua: 协程编程详解之从基础到多任务处理与应用实战

C++ 与 Lua 的协程交互 Lua 语言不支持真正的多线程,即不支持共享内存的抢占式线程。这样的模式能减少一些多线程的问题。多线程的问题源于线程抢占和共享内存,而如果非抢占式线程或者不使用共享内存则能避免多线程问题,Lua 同时支持这两种方案。Lua 语言的线程是协作式的,即协程,可以避免因不可预知的线程切换带来的问题。Lua 状态间内存不共享,所以各个状态相互独立运行,可以并行操作。Github传送门(如果对你有所帮助或喜欢的话,赏个star吧,码字不易,请多多支持)如果觉得本篇博文对你有所启发或是解决了困惑,。 阅读详情

协程基础与核心概念


1 ) 定义与特点

轻量级线程:在单线程内实现多任务协作,由程序显式控制切换(非抢占式)
资源开销低:每个协程独立堆栈(通常KB级),远低于操作系统线程(MB级)
适用场景:I/O密集型任务、状态机、游戏AI、异步逻辑等

2 ) 协程 vs 多线程

特性协程多线程
调度权程序显式控制(yield)操作系统抢占式调度
并发性协作式单核并发并行/多核并发
数据同步无需锁(单线程内)需互斥锁/信号量

2.1 示例:创建与启动协程

local co = coroutine.create(function(a, b)
    print("协程执行:", a, b)
    local result = coroutine.yield(a + b)  -- 挂起并返回a+b
    print("恢复执行,接收参数:", result)
    return "结束"
end)

local ok, sum = coroutine.resume(co, 10, 20)  -- 启动协程,传入参数
print("首次resume结果:", ok, sum)             -- 输出: true, 30

ok, msg = coroutine.resume(co, "新数据")      -- 恢复协程,传入"新数据"
print("二次resume结果:", ok, msg)             -- 输出: true, "结束"

--[[
协程执行:   10  20
首次resume结果: true    30
恢复执行,接收参数:  新数据
二次resume结果: true    结束
]]

2.2 示例:多个协程协作处理任务

local co1 = coroutine.create(function()
    for i = 1, 3 do
        print("协程1执行步骤", i)
        coroutine.yield() -- 暂停,让出控制权
    end
    print("协程1完成")
end)

local co2 = coroutine.create(function()
    for i = 1, 3 do
        print("协程2执行步骤", i)
        coroutine.yield() -- 暂停,让出控制权
    end
    print("协程2完成")
end)

--- 主线程调度两个协程交替执行
print("开始执行协程1")
coroutine.resume(co1)
print("开始执行协程2")
coroutine.resume(co2)
print("再次执行协程1")
coroutine.resume(co1)
print("再次执行协程2")
coroutine.resume(co2)
print("第三次执行协程1")
coroutine.resume(co1)
print("第三次执行协程2")
coroutine.resume(co2)

3 ) 协程生命周期与关键函数

3.1 状态流转

coroutine.create

coroutine.resume

yield

执行完毕

创建

Suspended

Running

Dead

3.2 核心函数解析

  • coroutine.create(f)
    • 创建协程,返回thread对象(状态为suspended)
  • coroutine.resume(co, ...)
    • 启动或恢复一个协程的执行
    • 首次调用:参数传递给协程函数
    • 后续调用:参数作为yield的返回值
    • 如果协程处于挂起或正常(normal)状态,resume会使其运行
    • 当协程执行到yield或结束时,控制权返回给resume的调用者
  • coroutine.yield(...):
    • 在协程内部调用,使协程暂停执行并返回到resume调用处
    • 协程的状态变为“挂起”
    • 挂起协程,参数作为resume的返回值
    • 恢复时接收resume传入的新参数
  • 状态检查示例
    print(coroutine.status(co))  -- 输出: suspended(创建后) → running(执行中) → dead(结束)
    

示例代码

--- 示例:演示协程生命周期
local co = coroutine.create(function(a, b)
    print("协程开始执行,参数:", a, b)
    local result = coroutine.yield("中间结果") -- 暂停并返回值
    print("协程恢复执行,从yield接收到:", result)
    return "最终结果"
end)

print("协程状态:", coroutine.status(co)) -- suspended

print("启动协程:")
local success, value = coroutine.resume(co, 10, 20) -- 传递参数给协程主函数
print("resume返回:", success, value) -- true, "中间结果"
print("协程状态:", coroutine.status(co)) -- suspended

print("再次启动协程:")
success, value = coroutine.resume(co, "恢复数据") -- 传递数据给yield
print("resume返回:", success, value) -- true, "最终结果"
print("协程状态:", coroutine.status(co)) -- dead

4 ) 协程与多任务处理

4.1 协作式多任务原理
事件循环调度:主线程轮询唤醒多个协程,避免阻塞
适用场景:网络请求批处理、游戏NPC行为序列

--- 模拟多任务调度器
local tasks = {}
local function add_task(f) table.insert(tasks, coroutine.create(f)) end
-- 任务示例:模拟耗时操作
add_task(function()
    for i = 1, 3 do
        print("Task1: step", i)
        coroutine.yield()
    end
end)

add_task(function()
    for i = 1, 2 do
        print("Task2: step", i)
        coroutine.yield()
    end
end)
-- 调度执行
while #tasks > 0 do
    for i = #tasks, 1, -1 do
        local ok = coroutine.resume(tasks[i])
        if coroutine.status(tasks[i]) == "dead" then
            table.remove(tasks, i)
        end
    end
end

--[[
Task2: step 1
Task1: step 1
Task2: step 2
Task1: step 2
Task1: step 3
]]

5 ) 协程在并发模型中的应用

5.1 生产者-消费者模式

local function producer()
    local i = 0 
    return function()
        while i < 5 do  -- 使用循环维持迭代状态 
            i = i + 1 
            coroutine.yield("数据-" .. i)
        end 
    end 
end
 
local co_producer = coroutine.wrap(producer())
 
local function consumer()
    while true do 
        local data = co_producer()
        if data == nil then break end  -- 显式检查nil终止 
        print("消费:", data)  -- 正确输出: 数据-1 到 数据-5 
    end
end

consumer()

--[[
消费: 数据-1
消费: 数据-2
消费: 数据-3
消费: 数据-4
消费: 数据-5
]]

5.2 非阻塞I/O处理(模拟)

local function async_http(url, callback)
    print("发起请求:", url)
    coroutine.yield()  -- 挂起协程 
    callback("响应数据:" .. url)
end

-- 创建协程并保存引用 
local co = coroutine.create(function()
    async_http("api/user", function(data) print(data) end)
    async_http("api/orders", function(data) print(data) end)
end)

-- 首次恢复协程(触发第一个请求)
coroutine.resume(co)

-- 模拟事件循环:分两次恢复协程以触发回调 
for _ = 1, 2 do
    print("处理响应...")
    coroutine.resume(co)  -- 复用已保存的协程引用 
end

--[[
发起请求:   api/user
处理响应...
响应数据:api/user
发起请求:   api/orders
处理响应...
响应数据:api/orders
]]

6 ) 高级技巧与陷阱

6.1 协程复用

local worker = coroutine.create(function(f, args)
    while f do 
        -- 执行函数并 yield 结果 
        f, args = coroutine.yield(f(table.unpack(args)))
    end 
end)
 
-- 首次调用:传入函数和参数表(单层结构)
local success, result = coroutine.resume(worker, math.abs, {-10})
print(result)  -- 输出: 10
 
-- 后续调用:继续复用协程
success, result = coroutine.resume(worker, string.upper, {"hello"})
print(result)  -- 输出: HELLO

--[[
10
HELLO
]]

6.2 错误处理

pcall包裹resume捕获异常:

local ok, err = pcall(coroutine.resume, co, bad_arg)

总结

场景协程优势
I/O密集型任务避免回调地狱,代码线性化
游戏逻辑简化状态机,NPC行为序列
资源受限环境低内存开销(对比线程)
Lua 协程 Lua里的协程是一个原来没见过的东西,Python的Gevent也是一个基于coroutine的python网络开发框架。性能据说很不错。 协同的一个关键特征是它可以不断颠倒调用者与被调用者之间的关系 协程和一般多线程的区别是,一般多线程由系统决定该哪个线程执行,是抢占式的,而协程是由每个线程自己决定自己什么时候不执行,并把执行权主动交给下一个线程。 协程是用户空间线程,操作系统其存在一无所知 阅读详情

相关推荐

【CTFhub】——hate_php2021

【CTFhub】——hate_php2021

manerzi的博客 1605

lua协程

Lua 协程(Coroutine)是一种轻量级的线程,也被称为协作式多线程。与操作系统管理的线程不同,协程是由程序自身来控制调度的,属于协作式多任务处理机制。这意味着协程只有在显式地让出执行权时,才会暂停执行,将控制权交给其他协程,而不是由操作系统强制切换。轻量级:创建和销毁协程的开销远小于创建和销毁线程。非抢占式调度:程序员可以精确控制协程的执行流程,避免了线程同步和锁带来的复杂性。Lua 协程通过协作式挂起和恢复机制,提供了轻量级的多任务处理能力。

m0_45371381的博客 1168

深入博通PEX89000内部:那颗ARM CPU和Synthetic Mode到底能玩出什么花样?

本文深入解析博通PEX89000系列PCIe交换芯片内置的ARM CPU与Synthetic Mode技术,揭示其在AI计算和数据中心的智能潜能。通过ARM Cortex CPU的实时控制和Synthetic Mode的自治网络功能,PEX89000实现了GPU集群的动态拓扑重组和资源池化,大幅提升AI训练效率。文章还探讨了该技术在软件定义数据平面和弹性AI架构中的创新应用。

weixin_30776273的博客 217

【Lua基础系列】协程

【Lua基础系列】协程 大家好,我是Lampard~~ 欢迎来到Lua进阶系列的博客 前文再续,书接上一回。今天和大家讲解一下lua中的协程 (一) 什么是协程 Lua 协同程序(coroutine)与线程(这里的线程指的是操作系统的线程)比较类似:拥有独立的堆栈,独立的局部变量,独立的指令指针,同时又与其它协同程序共享全局变量和其它大部分东西。 一个多线程程序可以同时运行几个线程(并发执行、抢占),而协程却需要彼此协作地运行,...

Lampard的博客 6442

【GEE实战指南】Python本地API配置避坑与一站式环境搭建

本文详细介绍了Google Earth Engine(GEE)Python本地API的配置避坑指南与一站式环境搭建流程。通过conda创建隔离环境、账户认证关键步骤、初始化代码的正确写法以及实战测试案例,帮助开发者快速掌握GEE Python API的配置技巧,避免常见错误,提升地理空间数据分析效率。

weixin_42624889的博客 187

为什么桥式传感器(Bridge Sensor)需要用到仪表放大器?

仪表放大器在桥式传感器的应用里起到关键作用,本文介绍桥式传感器的原理、特性,以及信号调理过程,并附上了一个 TINA - TI 的仿真电路。

疯狂的运放 1528

协程编程的奥秘:Lua中协程使用的全面解析与技巧分享

协程基础。 生产者-消费者问题。 协程相关API说明。 将协程用作迭代器。 事件驱动式编程。

Lion_Long的博客 2335

Python主要智能优化算法库汇总

最近几年简单浏览和对比了一些智能算法的库。现将各种库的主要信息、相关优缺点简单整理如下,各位同学可根据自己的需求和喜好进行选择。 文章目录1、DEAP2、mealpy3、scikit-opt (国产良心)4、Geat2(国产用心)5、pygmo26、pyswarms7、SciPy(想不到吧)小结 1、DEAP 项目地址:https://github.com/DEAP/deap 安装: pip install deap 优点: 起点高,发表在Journal of Machine Learning Rese

半个冯博士 2万+

Lua中协程相关函数使用详解

Lua中协程相关函数使用详解

你好 1481

基于STM32的双串口同时工作的详细指南(含完整代码示例)

STM32是STMicroelectronics(意法半导体)公司推出的一系列基于ARM Cortex-M内核的微控制器,广泛应用于嵌入式系统中。STM32系列微控制器具有高性能、低功耗和丰富的外设接口,适用于各种应用场景。USART(Universal Synchronous/Asynchronous Receiver/Transmitter)和UART(Universal Asynchronous Receiver/Transmitter)是串口通信的两种方式。

m0_57781768的博客 3805

使用WSL2安装ubuntu系统并配置深度学习环境

wsl2安装ubuntu部署深度学习环境的方法

u013358093的博客 2703

Lua : Coroutine(协程)

Lua 协程 基础知识详解

Mr.Sugarcane 1654

AI大模型驱动Web UI自动化测试:Playwright与RobotFramework智能整合实践

Web自动化测试是软件质量保障的关键环节,其核心原理是通过脚本模拟用户操作,对Web应用界面进行功能验证。传统方法依赖固定的元素定位和脚本逻辑,在应对频繁的UI变更时面临维护成本高、脚本脆弱的挑战。随着AI大模型技术的发展,其强大的自然语言理解和代码生成能力为自动化测试带来了新的技术价值。通过将大模型的意图理解与代码生成能力,与Playwright强大的浏览器自动化执行引擎以及RobotFramework灵活的关键字驱动框架相结合,可以构建出能够理解自然语言指令、动态生成稳定操作脚本的智能测试系统。这种融合

weixin_28718769的博客 415

Lua 从基础入门到精通:知识点详解与实战指南

Lua 是一种高级的、动态类型的脚本语言,设计目标是嵌入到应用程序中,提供灵活的扩展和定制功能。它由巴西里约热内卢天主教大学的研究小组于 1993 年开发。Lua 是一种轻量级、高效的脚本语言,广泛应用于游戏开发、嵌入式系统和 Web 开发。通过本文的介绍,读者可以全面掌握 Lua 的基础知识、核心特性、高级应用、框架支持和最佳实践。希望这些内容能帮助你在 Lua 的学习和开发中取得成功。

加入“Super Entity”,与全能开发团队共探AI智能体与数字人项目,开启前沿技术之旅。 1311

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Lua协程

目录 1.什么是协程 1.1 进程和线程 1.2 协程 1.2.1 协程挂起与唤醒 1.3 进程、线程和协程的区别 2.Lua协程 协程是追求极限性能和优美的代码结构的产物,协程允许我们写同步代码的逻辑,却做着异步的时,避免了回调嵌套,使得代码逻辑清晰。 1.什么是协程 1.1 进程和线程 在了解什么是协程之前,我们先要了解什么是进程和线程。 进程是应用程序的启动实例,比如我...

Martin的博客 1651

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Go与Lua协程交互详解:构建高效的混合编程模型

本文探讨了在Go语言中嵌入Lua虚拟机实现多场景应用架构的实践。通过引入场景设计提高系统灵活性,后台采用Go编写,场景逻辑使用Lua实现。重点讨论了Go与Lua的数据交互、协程冲突问题及解决方案。针对pcall会破坏协程上下文的问题,提出了协程包装器模式,有效分离全局事件与场景事件的处理。文章详细介绍了类型转换、函数注册等关键技术,并给出了多场景事件驱动模型的实现方案,为类似系统开发提供了参考。

wang_hengwen的博客 960

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Lua协程介绍

协程(coroutine)是一种程序组件,它允许执行代码在不同的点暂停和恢复,从而实现协作式的多任务处理。与传统的线程不同,协程不是由操作系统调度的,而是由程序自身控制的。因此,协程提供了一种轻量级的并发机制,适用于需要多任务但不需要真正并行的场景。

lzh824359508的博客 880

Lua 进阶指南:协程与多线程的实战应用

本文深入探讨Lua并发编程的两种核心方案:轻量级协程与基于Lua Lanes的多线程。详细解析了协程在I/O密集型场景下的高效协作式任务调度,以及多线程如何实现真正的并行计算以榨干多核CPU性能。通过实战代码对比,提供了清晰的选型指南与混合架构建议,帮助开发者根据实际场景选择最合适的并发模型。

i3j4k5的博客 479

Lua协程 基础和使用汇总

一、协程基础 简单介绍 lua协程和线程类似,拥有独立堆栈,独立局部变量;主要区别在于lua可以同时运行多个线程,但是在同一时刻只能有一个协程在运行,并且这个正在运行的协程只有在明确要求挂起的时候才会被挂起,比如调用yield,或者启动别的协程; coroutine.create(func) 创建一个线程,返回一个线程实例 coroutine.wrap(func) 创建一个协程,但是返回的是一个函数; coroutine.resume(co,...) 启动一个线程,并将参数传给调用的函数

mozhi 2189

Unity的协程和Lua的协程

本文分享Unity的协程和Lua的协程 协程(Coroutine)在我们游戏开发中有着比较重要的地位. 协程全名协同程序, 和线程不同, 协程是依附于主线程执行的, 相当于在主线程上夺取了一定的执行时间片. 也可以理解为在主线程的调用之外开辟了一个单独的调用栈, 并在协程消亡之前能保存内部信息和与其它协程共享公用信息. 协程实质是运行在主线程, 代码仍然是同步执行, 只是在某些点被挂起然后重新进行主线程其它代码的执行, 之后重新进入协程时可以从离开点继续执行. 这点和递归有些类似. 协程的核心概念有挂起和恢

木头圈 2029

Lua学习全攻略:从新手到高手的蜕变之路

学习Lua是一段充满挑战与收获的旅程。从基础语法的扎实掌握,到进阶特性的深入探索,再到通过实战项目将所学知识应用于实际,每一步都见证着我们在编程能力上的成长与进步。通过合理利用丰富的学习资源,如官方文档、在线教程和经典书籍,我们能够更加高效地学习Lua,不断提升自己的编程水平。希望大家在Lua的学习道路上坚持不懈,勇于探索,将Lua语言运用到更多的领域中,创造出更多精彩的项目 。

大雨淅淅的博客 1798

终极指南:NodeMCU Lua协程编程——告别阻塞,实现高效多任务并发

NodeMCU固件是一款基于Lua的交互式固件,专为ESP8266、ESP8285和ESP32设计,它通过协程和任务调度机制,让开发者能够轻松实现高效的多任务并发,彻底告别传统编程中的阻塞问题。本文将详细介绍如何利用NodeMCU的协程特性,编写非阻塞的应用程序,提升设备性能和响应速度。 ## 为什么选择协程?NodeMCU多任务的痛点与解决方案 🤔 在嵌入式开发中,传统的顺序执行代码往往会

gitblog_01154的博客 1085

lua协程 unity_XLua 之 Lua 协程 与 Unity 协程互通

前言:最近在摸索用XLua 在 Unity 中进行全Lua 开发。然后就遇到了协程的问题。我想在 Lua 侧开启一个 Unity 的协程,该怎么做呢?一开始我先去翻 XLua 的文档,我记得之前我看文档是看到过协程介绍的。但是快速翻了一遍后没找到(后来又找到了,本文最后会进行讲解)。然后就开始了自己的摸索。什么是协程?协程 是 协同程序 的简写。有过 Unity 或者 Lua 基础的朋友应该都已经...

weixin_32445333的博客 487

lua协程优秀实践:skynet

前言 本文主要讲解 lua 协程的基本使用,和它在 skynet 这个框架中的实际应用。 skynet简介 可能有的读者学 lua 不是做游戏服务器的,没有了解过 skynet,简单介绍下,skynet 是 云风 大神开发的开源服务器引擎,应用于当下众多的游戏公司的服务器框架。 lua协程是什么 从多线程(multithreading)的角度看,协程(coroutine)与线程(thread)类似:协程是一系列的可执行语句,拥有自己的栈、局部变量和指令指针,同时协程又与其他协程共享了全局变量和其他几乎一切

bo_self_effacing的博客 1292
上一篇: Lua: 基于协程的生产者-消费者模型实现
下一篇: Lua: 模块化编程深度解析之从基础到工程实践
Wang's Blog
博客等级 码龄12年 7438粉丝 2422原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值