协同程序与线程thread差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和命令指针,同时又与其他协同程序共享全局变量和其他大部分东西。从概念上讲线程与协同程序的主要区别在于,一个具有多个线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。也就是说多个协同程序在任意时刻只能运行一个协同程序,只有当正在运行的协同程序显式的要求挂起时,它的执行才会暂停。

 
一、协同程序coroutine
 
     Lua将所有关于协同程序的函数放置在一个名为“coroutine”的table中。
     1、coroutine.create创建一个thread类型的值表示新的协同程序,返回一个协同程序。
     2、coroutine.status检查协同程序的状态(挂起suspended、运行running、死亡dead、正常normal)。
     3、coroutine.resume启动或再次启动一个协同程序,并将其状态由挂起改为运行。
     4、coroutine.yield让一个协同程序挂起。
     5、coroutine.wrap同样创建一个新的协同程序,返回一个函数。
 
     创建协同程序:create函数,接受一个函数值作为协同程序的执行内容,并返回一个协同程序。
 
 
     启动或再次启动一个协同程序:resume函数,接受一个协同程序及一个或多个参数用于值传递给协同程序。
 
 
     挂起协同程序:yield函数,让一个协同程序挂起,并等待下次恢复它的运行。它可以接受resume函数传递进来的所有参数。
 
 
     关于wrap函数的使用,wrap函数比create函数更易使用。它提供了一个对于协同程序编程实际所需的功能,即一个可以唤醒协同程序的函数。但也缺乏灵活性。无法检查wrap所创建的协同程序的状态,此外,也无法检测出运行时的错误。
 
 
     各种协同状态的演示:
 
 
     首先,Lua提供的是一种:”非对称的协同程序“。也就是说,Lua提供了两个函数来控制协同程序的执行,一个用于挂起执行,另一个用于恢复执行。而一些其他的语言则提供了”对称的协同程序“,其中只有一个函数用于转让协同程序之间的执行权。
 
二、管道与过滤器filter
 
     关于协同程序的示例就是”生产者--消费者“的问题。其中涉及到两个函数,一个函数不断的产生值,另一个函数不断的消费这些值。当消费者需要一个新的值时,它唤醒生产者。生产者返回一个新值后停止运行,等待消费者的再次唤醒。这种设计称为”消费者驱动“。通过resume—yield 函数之间的值交换可以轻易的实现程序。
 
     过滤器filter,是一种位于生产者与消费者之间的处理功能,可以进行数据转换。它既是消费者又是生产者,它唤醒生产者促使其生产新值,然后又将变换后的值传递给消费者。
 
 --管道与过滤器filter
--生产者与消费者通过过滤器进行值传递
--这种模式通过消费者驱动生产者进行产生。 --计数器函数
function getCount( x )
return function()
x=x+
return x
end
end
--创建闭合计数器
local count = getCount()
--发送新值
function send(x)
coroutine.yield(x)
end
--启动一个协同程序
function receive( pro )
local status,value = coroutine.resume( pro )
return value
end
--生产者
function producter()
while true do
send( count() )
end
end
--过滤器,接受一个生产者
function filter( pro )
local x =
return function()
while true do
x = receive( pro )
send(x)
end
end
end
--消费者,接受一个生产者协同程序及控制条件,控制条件防止死循环
--假设有100个消费者,驱动生产者来生产
function consumer( pro,num )
local x =
while x < num do
x = receive( pro )
print( x )
end
end local pro = coroutine.create( producter )
local fil = coroutine.create( filter( pro ) )
consumer( fil, ) print( "消费者协同程序状态:",coroutine.status(pro) )
print( "生产者协同程序状态:",coroutine.status(fil) )

 

三、协同程序实现的迭代器
 
     通过“生产者—消费者”模型可以很轻松的创建迭代器,同样是通过协同程序来进行控制。
 
--以协同程序实现Lua迭代器

local tab = { ,,,,, }

function corFun( tab,num )
num = num or
return function()
while true do
num = num +
if( num > #tab ) then return end
coroutine.yield(tab[num])
end
end
end function cor( tab )
local cor = coroutine.create( corFun( tab ) )
return function ()--迭代器
local status,value = coroutine.resume( cor )
return value
end
end for v in cor( tab ) do
if v then
print(v)
else
break
end
end

 

Lua 学习笔记(九)协同程序(线程thread)的更多相关文章

  1. 《C#并发编程经典实例》学习笔记-进程(process)和线程(thread)

    本文主要参考自孙钟秀主编的<操作系统教程>一书中关于进程和线程的部分. 进程 为什么引入进程? 一,刻画系统动态性,发挥系统并发性,提高资源利用率. 以C#为例,在编辑器Visual St ...

  2. Lua学习笔记4. coroutine协同程序和文件I/O、错误处理

    Lua学习笔记4. coroutine协同程序和文件I/O.错误处理 coroutine Lua 的协同程序coroutine和线程比较类似,有独立的堆栈.局部变量.独立的指针指令,同时又能共享全局变 ...

  3. 多线程学习笔记九之ThreadLocal

    目录 多线程学习笔记九之ThreadLocal 简介 类结构 源码分析 ThreadLocalMap set(T value) get() remove() 为什么ThreadLocalMap的键是W ...

  4. Android(java)学习笔记267:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  5. Android(java)学习笔记211:Android线程池形态

    1. 线程池简介  多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力.     假设一个服务器完成一项任务所需时间为:T1 创建线程时间, ...

  6. JavaSE学习笔记(13)---线程池、Lambda表达式

    JavaSE学习笔记(13)---线程池.Lambda表达式 1.等待唤醒机制 线程间通信 概念:多个线程在处理同一个资源,但是处理的动作(线程的任务)却不相同. 比如:线程A用来生成包子的,线程B用 ...

  7. JavaSE学习笔记(12)---线程

    JavaSE学习笔记(12)---线程 多线程 并发与并行 并发:指两个或多个事件在同一个时间段内发生. 并行:指两个或多个事件在同一时刻发生(同时发生). 在操作系统中,安装了多个程序,并发指的是在 ...

  8. 转:学习笔记: Delphi之线程类TThread

    学习笔记: Delphi之线程类TThread - 5207 - 博客园http://www.cnblogs.com/5207/p/4426074.html 新的公司接手的第一份工作就是一个多线程计算 ...

  9. [转]LUA 学习笔记

    Lua 学习笔记 入门级 一.环境配置 方式一: 1.资源下载http://www.lua.org/download.html 2.用src中的源码创建了一个工程,注释调luac.c中main函数,生 ...

随机推荐

  1. 从问题看本质:socket到底是什么?

    一.问题的引入——socket的引入是为了解决不同计算机间进程间通信的问题 1.socket与进程的关系 1).socket与进程间的关系:socket   用来让一个进程和其他的进程互通信息(IPC ...

  2. 设置Flush刷新模式setFlushMode()

    参考 http://blog.csdn.net/superdog007/article/details/38852399 FlushMode的枚举值: FlushMode.ALWAYS:任务一条SQL ...

  3. 不同类型的指针+1之后增加的大小不同(a,&a的地址是一样的,但意思不一样)

    main() { ]={,,,,}; ); printf(),*(ptr-)); } *(a+1)就是a[1],*(ptr-1)就是a[4], 执行结果是2, 5.&a+1不是首地址+1,系统 ...

  4. 订单支付成功后存储过程 - MYSQL

    BEGIN SET @userId = (SELECT user_id FROM t_shoporder WHERE id = orderId); /*修改订单状态,改成已支付*/ ,update_t ...

  5. LoadingView

    // //  LoadingView.h //  蓝桥播报 // //  Created by 小小建 on 15/7/10. //  Copyright (c) 2015年 蓝桥. All righ ...

  6. 跨平台移动开发UI语言 -XAML

    Xamarin.Forms 把XAML (Extensible Application Markup Language, XAML) 带进了ios,android的界面开发,也就使得使用Xamarin ...

  7. .NET短距离领域通信-32feet.NET

    32feet.NET[http://32feet.codeplex.com/]是shared-source的项目,支持CF.net 2.0以及桌面版本.NET framework,提供短距离领域(pe ...

  8. UI控件(UIScrollView)

    @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; //创建一个scrollview UIScrollV ...

  9. Hadoop学习笔记—15.HBase框架学习(基础知识篇)

    HBase是Apache Hadoop的数据库,能够对大型数据提供随机.实时的读写访问.HBase的目标是存储并处理大型的数据.HBase是一个开源的,分布式的,多版本的,面向列的存储模型,它存储的是 ...

  10. ASP.Net MVC开发基础学习笔记:二、HtmlHelper与扩展方法

    一.一个功能强大的页面开发辅助类—HtmlHelper初步了解 1.1 有失必有得 在ASP.Net MVC中微软并没有提供类似服务器端控件那种开发方式,毕竟微软的MVC就是传统的请求处理响应的回归. ...