【深入Lua】理解Lua中最强大的特性-coroutine(协程)

2023-11-23 06:48

本文主要是介绍【深入Lua】理解Lua中最强大的特性-coroutine(协程),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

http://my.oschina.net/wangxuanyihaha/blog/186401

coroutine基础

Lua所支持的协程全称被称作协同式多线程(collaborative multithreading)。Lua为每个coroutine提供一个独立的运行线路。然而和多线程不同的地方就是,coroutine只有在显式调用yield函数后才被挂起,同一时间内只有一个协程正在运行。

Lua将它的协程函数都放进了coroutine这个表里,其中主要的函数如下

表格

摘取一段云风的代码来详尽解释协程的工作机制,在这段代码中,展示了main thread和协程co之间的交互:


function foo(a)print("foo", a)return coroutine.yield(2 * a)
endco = coroutine.create(function ( a, b )print("co-body", a, b)local r = foo(a + 1)print("co-body", r)local r, s = coroutine.yield(a + b, a - b)print("co-body", r, s)return b, "end"
end)print("main", coroutine.resume(co, 1, 10))
print("main", coroutine.resume(co, "r"))
print("main", coroutine.resume(co, "x", "y"))
print("main", coroutine.resume(co, "x", "y"))

下面是运行结果

co-body 1 10
foo 2
main true 4
co-body r
main true 11, -9
co-body x y
main false 10 end
main false cannot resume dead coroutine

coroutine和subroutine(子例程)的比较

子例程的起始处是唯一的入口点,一旦return就完成了子程序的执行,子程序的一个实例只会运行一次。

但是协程不一样,协程可以使用yield来切换到其他协程,然后再通过resume方法重入(reenter)到上次调用yield的地方,并且把resume的参数当成返回值传给了要重入(reenter)的协程。但是coroutine的状态都没有被改变,就像一个可以多次返回的subroutine

协程的精妙之处就在于协作这一概念,下面我们用生产者和消费者问题来演示一下协程的基本应用。注意:下面的伪码是用Lua的思想写的

var q = queue()

生产者的伪码

loopwhile q is not fullcreate productadd the items to qresume to consumer

消费者的伪码

loopwhile q is not emptyconsume productremove the items from qyield

coroutine的和callback的比较

coroutine经常被用来和callback进行比较,因为通常来说,coroutine和callback可以实现相同的功能,即异步通信,比如说下面的这个例子:


bob.walkto(jane)
bob.say("hello")
jane.say("hello")

看起来好像是对的,但实际上由于这几个动作walkto,say都是需要一定时间才能做完的,所以这段程序如果这样写的话,就会导致bob一边走一边对jane说hello,然后在同时jane也对bob说hello,导致整个流程十分混乱。

如果使用回调来实现的话,代码示例如下:


bob.walto(function (  )bob.say(function (  )jane.say("hello")end,"hello")
end, jane)

即walto函数回调say函数,say函数再回调下一个say函数,这样回调看起来十分混乱,让人无法一下看出这段代码的意义.

如果用coroutine的话,可以使用如下写法:


co = coroutine.create(function (  )local current = coroutine.runningbob.walto(function (  )coroutine.resume(current)end, jane)coroutine.yield()bob.say(function (  )coroutine.resume(current)end, "hello")coroutine.yield()jane.say("hello"end)coroutine.resume(co)

在上述代码中,一旦一个异步函数被调用,协程就会使用coroutine.yield()方法将该协程暂时悬挂起来,在相应的回调函数中加上coroutine.resume(current),使其返回目前正在执行的协程中。

但是,上述代码中有许多重复的地方,所以可以通过将封装的方式将重复代码封装起来


function runAsyncFunc( func, ... )local current = coroutine.runningfunc(function (  )coroutine.resume(current)end, ...)coroutine.yield()
endcoroutine.create(function (  )runAsyncFunc(bob.walkto, jane)runAsyncFunc(bob.say, "hello")jane.say("hello")
end)coroutine.resume(co)

这样就不需要改变从前的所有回调函数,即可通过携程的方式解决异步调用的问题,使得代码的结构非常清晰。


这篇关于【深入Lua】理解Lua中最强大的特性-coroutine(协程)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/416119

相关文章

深入解析Spring TransactionTemplate 高级用法(示例代码)

《深入解析SpringTransactionTemplate高级用法(示例代码)》TransactionTemplate是Spring框架中一个强大的工具,它允许开发者以编程方式控制事务,通过... 目录1. TransactionTemplate 的核心概念2. 核心接口和类3. TransactionT

Rsnapshot怎么用? 基于Rsync的强大Linux备份工具使用指南

《Rsnapshot怎么用?基于Rsync的强大Linux备份工具使用指南》Rsnapshot不仅可以备份本地文件,还能通过SSH备份远程文件,接下来详细介绍如何安装、配置和使用Rsnaps... Rsnapshot 是一款开源的文件系统快照工具。它结合了 Rsync 和 SSH 的能力,可以帮助你在 li

深入理解Apache Airflow 调度器(最新推荐)

《深入理解ApacheAirflow调度器(最新推荐)》ApacheAirflow调度器是数据管道管理系统的关键组件,负责编排dag中任务的执行,通过理解调度器的角色和工作方式,正确配置调度器,并... 目录什么是Airflow 调度器?Airflow 调度器工作机制配置Airflow调度器调优及优化建议最

一文带你理解Python中import机制与importlib的妙用

《一文带你理解Python中import机制与importlib的妙用》在Python编程的世界里,import语句是开发者最常用的工具之一,它就像一把钥匙,打开了通往各种功能和库的大门,下面就跟随小... 目录一、python import机制概述1.1 import语句的基本用法1.2 模块缓存机制1.

深入理解C语言的void*

《深入理解C语言的void*》本文主要介绍了C语言的void*,包括它的任意性、编译器对void*的类型检查以及需要显式类型转换的规则,具有一定的参考价值,感兴趣的可以了解一下... 目录一、void* 的类型任意性二、编译器对 void* 的类型检查三、需要显式类型转换占用的字节四、总结一、void* 的

深入理解Redis大key的危害及解决方案

《深入理解Redis大key的危害及解决方案》本文主要介绍了深入理解Redis大key的危害及解决方案,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着... 目录一、背景二、什么是大key三、大key评价标准四、大key 产生的原因与场景五、大key影响与危

五大特性引领创新! 深度操作系统 deepin 25 Preview预览版发布

《五大特性引领创新!深度操作系统deepin25Preview预览版发布》今日,深度操作系统正式推出deepin25Preview版本,该版本集成了五大核心特性:磐石系统、全新DDE、Tr... 深度操作系统今日发布了 deepin 25 Preview,新版本囊括五大特性:磐石系统、全新 DDE、Tree

深入理解C++ 空类大小

《深入理解C++空类大小》本文主要介绍了C++空类大小,规定空类大小为1字节,主要是为了保证对象的唯一性和可区分性,满足数组元素地址连续的要求,下面就来了解一下... 目录1. 保证对象的唯一性和可区分性2. 满足数组元素地址连续的要求3. 与C++的对象模型和内存管理机制相适配查看类对象内存在C++中,规

【前端学习】AntV G6-08 深入图形与图形分组、自定义节点、节点动画(下)

【课程链接】 AntV G6:深入图形与图形分组、自定义节点、节点动画(下)_哔哩哔哩_bilibili 本章十吾老师讲解了一个复杂的自定义节点中,应该怎样去计算和绘制图形,如何给一个图形制作不间断的动画,以及在鼠标事件之后产生动画。(有点难,需要好好理解) <!DOCTYPE html><html><head><meta charset="UTF-8"><title>06

认识、理解、分类——acm之搜索

普通搜索方法有两种:1、广度优先搜索;2、深度优先搜索; 更多搜索方法: 3、双向广度优先搜索; 4、启发式搜索(包括A*算法等); 搜索通常会用到的知识点:状态压缩(位压缩,利用hash思想压缩)。