读《Programming In Lua》协程那一章,比较困惑的还是procuer-consumer那个例子:

function consumer(prod)while true dolocal x = receive(prod)print(x)end
endfunction receive(prod)local status, value = coroutine.resume(prod)return value
endfunction send(x)coroutine.yield(x) -- go back to where resumed
endfunction producer()return coroutine.create(function()while true dolocal x = io.read()send(x)endend)
end-- consumer-driven design
consumer(producer())

producer产生数据,consumer消费数据,producer与consumer都在各自的协程中完成, 代码很短,但是很难读 - 至少不是那么一目了然,尤其比起这个直接的循环:

function produce()return io.read()
endfunction consume(x)print(x)
endwhile true dolocal x = produce()consume(x)
end

好在哪里?

书中说可以添加缓存控制速度,或者进行数据过滤 - 但是这在循环版本的producer-consumer中也都能做到,无非在在实现produce是多些逻辑,或者再加个filter的函数处理produce的返回值,协程版本毫无优势可言。

实在要说其优点,恐怕只是:producer和consumer的代码在各自的协程中实现,并通过resume-yield交换数据 - 实现了松耦合。这是个优点,可以还是不太满意,再往下看时,看到了全排列那个例子,稍作修改,让我比较直观的感觉到了协程这种控制结构的灵活性:

function send(a)coroutine.yield(a)
endfunction receive(prod)local status, value = coroutine.resume(prod)return value
endfunction consumer(prod)local function print_result(a)for _, v in ipairs(a) doio.write(v, " ")endio.write('\n')endwhile true dolocal a = receive(prod)if not a then break endprint_result(a)end
endfunction producer(a)function permgen(a, n)if n == 0 thensend(a) -- send something for consuming from an recursive callelsefor i=1, n doa[n], a[i] = a[i], a[n]permgen(a, n-1)a[n], a[i] = a[i], a[n]endendendlocal n = table.getn(a)return coroutine.create(function() permgen(a, n) end)
endconsumer(producer({1,2,3,4}))

这里全排列采用了递归算法:对数组中的每个元素,把它交换到数组末尾,然后对前n-1个元素的子数组做同样的事,当n==0时,输出一个排列。

这个在produce的时候,因为在一个递归调用中,你无法一个个返回:

  • 要么每找到一个,直接在里面处理 - 这样produce-consume的结构就有点混淆在一起;
  • 或者先把结果保存在一个共享内存中,产生全部排列后,再逐个处理 - 这样要另外开辟空间,流程上感觉也不够简洁。

于是,协程的有点就显现出来了,不同于简单函数中的return,协程可以在找到一个排列后,yield挂起本协程并返回该排列,返回到原来resume这个协程的代码处,取得数据进行consume,然后继续resume进入协程获取排列 - 通过协程灵活控制流程并传递数据,十分漂亮。

所以,那个循环版本的问题是:并不是所有produce的数据,都可以简单的return回来的。

转载于:https://www.cnblogs.com/baiyanhuang/archive/2012/11/17/2775315.html

对lua协程的一点理解相关推荐

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

    前言: 最近在摸索用XLua 在 Unity 中进行全Lua 开发.然后就遇到了协程的问题.我想在 Lua 侧开启一个 Unity 的协程,该怎么做呢? 一开始我先去翻 XLua 的文档,我记得之前我 ...

  2. Lua协程Coroutine是什么

    Lua协程Coroutine是什么 协程和线程不同: 同一时刻,一个多线程程序可以用多个线程同时执行:而协程只能有一个在执行 多线程是抢占式的:而协程是非抢占式的,只有协程显示被挂起,才会被挂起 协程 ...

  3. Unity协程实现分析以及Lua协程与Unity协程的混合使用

    1,节选翻译一篇stackoverflow关于Unity协程实现的讨论 - The big clues are in the C# version. Firstly, note that the re ...

  4. Lua 协程和线程区别

    协程就是协程,不是线程. CPU执行单位是线程,不是什么协程. 协程,是同步执行,不是并行,只是切了一个上下文了,为你保存原来的上下文而已. 切到第二个协程时,原来的协程处于挂起状态. 这个特指lua ...

  5. lua协程 unity_unity协程coroutine浅析

    一.序言 在unity的游戏开发中,对于异步操作,有一个避免不了的操作: 协程,以前一直理解的懵懵懂懂,最近认真充电了一下,通过前辈的文章大体理解了一下,在这儿抛砖引玉写一些个人理解.当然首先给出几篇 ...

  6. 关于进程,线程,协程,一点心得

    1:进程 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动,是系统进行资源分配和调度的基本单位,是操作系统结构的基础.在当代面向线程设计的计算机结构中,进程是线程的容器,一个进程中 ...

  7. go 怎么等待所有的协程完成_理解真实世界中 Go 的并发 BUG

    点击上方蓝色"Go语言中文网"关注,回复「电子书」领全套Go资料 有几个学生研究归纳了go编程中的并发bugs,发表了一篇(英文)论文:<Understanding Real ...

  8. python3 协程 写法_理解Python的协程(Coroutine)

    由于GIL的存在,导致Python多线程性能甚至比单线程更糟. GIL: 全局解释器锁(英语:Global Interpreter Lock,缩写GIL),是计算机程序设计语言解释器用于同步线程的一种 ...

  9. LUA 协程 Coroutine

    协程 Coroutine 协程(coroutine)并不是 Lua 独有的概念,如果让我用一句话概括,那么大概就是:一种能够在运行途中主动中断,并且能够从中断处恢复运行的特殊函数.(嗯,其实不是函数. ...

最新文章

  1. 更简单的非递归遍历二叉树的方法
  2. c#如何跳出一个函数_C#初学者教程系列9:类和对象
  3. 《高性能JavaScript》第五章 字符串和正则表达式
  4. DTCC 2020 | 阿里云吉剑南:在线分析进入Fast Data时代的关键技术解读
  5. 改变UITextField placeHolder颜色、字体
  6. 使用Apriori进行关联分析(二)
  7. 无法转化为项目财富的技术或功能就是垃圾
  8. python零基础学习书-零基础学习python推荐几本书?
  9. state 全局值 设置 和获取
  10. MySQL数据库简单了解
  11. matlab时频分析工具箱安装,Matlab emd工具箱、时频分析工具箱下载以及安装方法...
  12. Gitlab-Runner安装并注册
  13. P3376 (最大流 dinic)
  14. 学习AngularJs:Directive指令用法
  15. 生活家健康指南:创可贴使用四大误区
  16. 初识智遥工作流软件——表单开发篇1
  17. 基于可见光通信的移动机器人室内定位及物联网应用
  18. Virtual Machine Monitors——VMM总结
  19. 河边的小屋原来是这么俗气的一个名字
  20. RPC编程:Hessian RPC一个老的RPC框架(一)

热门文章

  1. Applications Manager Docker监控
  2. 为Tiny4412设备驱动在proc目录下添加一个可读版本信息的文件
  3. Undefined symbols for architecture i386:_OBJC_CLASS_$_xx, referenced from: 解决方法
  4. 《SQL初学者指南(第2版)》——2.4 指定列
  5. bind安装配置以及应用
  6. Linux下C++ UDP Socket例子
  7. Develop内部函数,持续更新
  8. mysql select array_从数据库select查询出来的数组
  9. jdbctemplate mysql 配置_Spring JDBCTemplate配置使用
  10. str045漏洞提权linux,Linux运维知识之CVE-2016-5195 Dirtycow: Linux内核提权漏洞