《Lua程序设计》9.1 协同程序基础 学习笔记
协同程序(coroutine)与线程(thread)差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针,同时又与其他协同程序共享全局变量和其他大部分东西。从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作地运行。就是说,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显式地要求挂起(suspend)时,它的执行才会暂停。
Lua将所有关于协同程序的函数放置在一个名为“coroutine”的table中。函数create用于创建新的协同程序,它只有一个参数,就是一个函数。该函数的代码就是协同程序所需执行的内容。create会返回一个thread类型的值,用以表示新的协同程序。通常create的参数是一个匿名函数,例如:
co = coroutine.create(function () print("hi") end)
print(co) --> thread: 0x8071d98
一个协同程序可以处于4种不同的状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。当创建一个协同程序时,它处于挂起状态。也就是说,协同程序不会在创建它时自动执行其内容。可以通过函数status来检查协同程序的状态:
print(coroutine.status(co)) --> suspended
函数coroutine.resume用于启动或再次启动一个协同程序的执行,并将其状态由挂起改为运行:
coroutine.resume(co) --> hi
在本例中,协同程序的内容指示简单地打印了“hi”后便终止了,然后它就处于死亡状态,也就再也无法返回了:
print(coroutine.status(co)) --> dead
到目前为止,协同程序看上去还指示像一种复杂的函数调用方法。骑士协同程序的真正强大指出在于函数yield的使用上,该函数可以让一个运行中的协同程序挂起,而之后可以再恢复它的运行。请看下面的这个简单的示例:
co = coroutine.create(function ()
for i=, do
print("co", i)
coroutine.yield()
end
end)
现在当唤醒这个协同程序时,它就会开始执行,知道第一个yield:
coroutine.resume(co) --> co 1
如果此时检查器状态,会发现协同程序处于挂起状态,因此可以再次恢复其运行:
print(coroutine.status(co)) --> suspended
从协同程序的角度看,所有在它挂起时发生的活动都发生在yield调用中。当恢复协同程序的执行时,对于yield的调用才最终返回。然后协同程序继续执行它的执行,知道下一个yield调用或执行结束:
coroutine.resume(co) --> co 2
coroutine.resume(co) --> co 3
...
coroutine.resume(co) --> co 10
coroutine.resume(co) -- 什么都不打印
在最后一次调用resume时,协同程序的内容已经执行完毕,并已经返回。因此,这时协同程序处于死亡状态。如果试图再次恢复它的执行,resume将false及一条错误消息:
print(coroutine.resume(co)) --> false cannot resume dead coroutine
resume是在保护模式中运行的。因此,如果在一个协同程序的执行中发生任何错误,Lua是不会显示错误消息的,而是将执行权返回给resume调用。
当一个协同程序A唤醒另一个协同程序B时,协同程序A就处于一种特殊状态,既不是挂起状态(无法继续A的执行),也不是运行状态(是B在运行)。所以将这时的状态称为“正常”状态。
Lua的协同程序还具有一项有用的机制,就是可以通过一对resume-yield来交换数据。在第一次调用resume时,并没有对应的yield在等待它,因此所有传递给resume的额外参数都将视为协同程序主函数的参数:
co = coroutine.create(function (a,b,c)
print("co", a,b,c)
end)
coroutine.resume(co, , , ) --> co 1 2 3
在resume调用返回的内容中,第一个值为true则表示没有错误,而后面所有的值都是对应yield传入的参数:
co = coroutine.create(function (a,b)
coroutine.yield(a+b, a-b)
end)
print(coroutine.resume(co, , )) --> true 30 10
与此对应的是,yield返回的额外值就是对应resume传入的参数:
co = coroutine.create (function ()
print("co", coroutine.yield())
end)
coroutine.resume(co)
coroutine.resume(co, , ) --> co 4 5
最后,当一个协同程序结束时,它的主函数所返回的值都将作为对应resume的返回值:
co = coroutine.create(function ()
return ,
end)
print(coroutine.resume(co)) --> true 6 7
很少在同一个协同程序中使用所有这些功能,但每种功能各有其用途。
Lua提供的是一种“非对称的协同程序(asymmetric coroutine)”。也就是说,Lua提供了两个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。而一些其他的语言则提供了“堆成的协同程序(symmetric coroutine)”,其中只有一个函数用于转让协同程序之间的执行权。
《Lua程序设计》9.1 协同程序基础 学习笔记的更多相关文章
- 《Lua程序设计》第1章 开始 学习笔记
1.1 程序块(chunk)每段代码(例如一个源代码文件或在交互模式中输入的一行代码),称为一个程序块.若使用命令行参数-i来启动Lua解释器,那么解释器就会在运行完指定程序块后进入交互模式.dofi ...
- 《Lua程序设计》第5章 函数 学习笔记
Lua为面向对象式的调用也提供了一种特殊的语法——冒号操作符.表达式o.foo(o, x)的另一种写法是o:foo(x),冒号操作符是调用o.foo时将o隐含地作为函数的第一个参数.Lua可以调用C语 ...
- 《Lua程序设计》第4章 语句 学习笔记
Lua中的常规语句包括:赋值.控制结构和过程调用.Lua还支持一些不太常见的语句,如:多重赋值(multiple assignment) 和 局部变量声明.4.1 赋值Lua允许“多重赋值”,也就是一 ...
- 《Lua程序设计》第3章 表达式 学习笔记
3.1 算术操作符“+”(加法).“-”(减法).“*”(乘法).“/”(除法).“^”(指数).“%”(取模).3.2 关系运算符< > <= >= == ~=3.3 逻辑操 ...
- 尚学堂JAVA基础学习笔记
目录 尚学堂JAVA基础学习笔记 写在前面 第1章 JAVA入门 第2章 数据类型和运算符 第3章 控制语句 第4章 Java面向对象基础 1. 面向对象基础 2. 面向对象的内存分析 3. 构造方法 ...
- 1.C#基础学习笔记3---C#字符串(转义符和内存存储无关)
技术qq交流群:JavaDream:251572072 教程下载,在线交流:创梦IT社区:www.credream.com ------------------------------------- ...
- 0003.5-20180422-自动化第四章-python基础学习笔记--脚本
0003.5-20180422-自动化第四章-python基础学习笔记--脚本 1-shopping """ v = [ {"name": " ...
- C#RabbitMQ基础学习笔记
RabbitMQ基础学习笔记(C#代码示例) 一.定义: MQ是MessageQueue,消息队列的简称(是流行的开源消息队列系统,利用erlang语言开发).MQ是一种应用程序对应用程序的通信方法. ...
- 基础学习笔记之opencv(6):实现将图片生成视频
基础学习笔记之opencv(6):实现将图片生成视频 在做实验的过程中.难免会读视频中的图片用来处理,相反将处理好的图片又整理输出为一个视频文件也是非经常常使用的. 以下就来讲讲基于opencv的C+ ...
随机推荐
- c 变量的存储类型auto等(基础知识)和c函数变量
总结 1).在c语言中每一个变量和函数有两个属性:数据类型和数据的存储类别. 2). 对数据型(如整型.字符型等).存储类别指的是数据在内存中存储的方式. 存储方式分为两大类: 静态存储类和动态存储类 ...
- Android 耳机插入过程分析
Android 耳机插入过程分析 参考链接: https://www.jianshu.com/p/d82a8dabb3e7 初始化: 10-26 07:40:43.932 1414 1414 I Sy ...
- android wifi RSSI达到阈值自动断开
设置wifi的RSSI达到阈值之后自动断开. wifi状态改变,会更新状态栏,在状态栏中更改. --- a/packages/SystemUI/src/com/android/systemui/sta ...
- Dynamics CRM 2015/2016 Web API:聚合查询
各位小伙伴们,今天是博主2016年发的第一篇文章.首先祝大家新年快乐.工资Double,哈哈.今天我们来看一个比較重要的Feature--使用Web API运行FetchXML查询! 对的,各位.你们 ...
- EasyUI的功能树之异步树
最近几个项目都用到了EasyUI这个Jquery框架,目前感觉起来还是很好使的,展示效果很好,帮助文档什么的资料很多,而且互联网上Easy粉很多,大多数拥护和喜爱EasyUI的粉丝们都愿意在网络平台互 ...
- Linux下修改MySql的root密码
linux下如何修改Mysql的root密码 今天,忘了mysql下的root密码,想重置一下,但找了多个网站上的方法均有问题,最后参考几家的过程,经过不断尝试获得,终于成功了,下面特将过程分 ...
- 图解HTTP学习笔记——确认访问用户身份的认证
前言 认证功能能让Web页面只被有权限的人访问.而认证机制究竟是怎样一个原理呢?通过今天的学习能对这个有个大致的了解. 正文 什么是认证 计算机无法判断对方的身份,需要客户端自报家门. 服务端为确认客 ...
- Sublime的插件Color Highlighter的安装方法
ColorHighlighter是一个显示选中颜色代码的视觉颜色的插件.如果您选择“# fff“,它将向您展示白色.ColorHighlighter支持所有CSS颜色格式,如Hex,RGB,HSL,H ...
- Kafka监控工具KafkaOffsetMonitor配置及使用
转载:https://www.cnblogs.com/dadonggg/p/8242682.html jar包下载地址 KafkaOffsetMonitor托管在Github上,可以通过Github下 ...
- 多线程二(GCD)代码笔记
// // TWFXViewController.h // Demo_GCD // // Created by Lion User on 12-12-11. // Copyright (c) 2012 ...