本节大概地讲一下关于协同程序的知识点。
在前面我们讲了lua的数据类型种类的时候,我们讲过thread这种类型,本节就讲这种类型是如何创建的,以及如何使用它。
协同程序(coroutine)跟多线程有相似之处,拥有自己的局部变量,栈空间,变量指针等,也拥有共享的全局变量。
但二者还是有一定的区别:多线程可以同时运行多个线程,而协同程序一个时候只能运行一个,并且只有在显式调用挂起之后,才会使协同程序暂停下来。
LUA将有关协同程序的函数都封装于coroutine这个table里边,同时,一个协同程序拥用“运行”“挂起”“正常”,以及“死亡”这四种状态
举例:
创建一个协同程序,此时
c = coroutine.create(function() print 'create the coroutine programming!!' end);
打印协同程序的返回类型
print(c) ---thread:0x12382364
打印协同程序的状态(一个刚创建的协同程序,状态都是挂起,必须通过显示调用resume,才能让挂起的协同变成运行状态)
print(coroutine.status(c)) ---suspended
通过显示调用resume,才能让挂起的协同变成运行状态,但由于程序只是打印了一个create the coroutine programming!!字符串,所以最后直接由运行状态变成死亡状态了。
coroutine.resume(c)
print(coroutine.status(c)) ---dead
协同程序的正常状态,是指当协同A程序调用了协同B程序时,A程序便处于正常状态。
LUA通过coroutine.yeild()这个强大的函数,让协同程序从运行状态变成挂起状态
---------------------------------------------------------------
下面我们重新编写协同程序的主函数,如下:
c = coroutine.create(function() for i=1,10 do print("coroutine",i) coroutine.yield() end end);
让协同程序c跑起来(suspended->running)
coroutine.resume(c)-- coroutine 1
print(coroutine.status(c))--suspended 执行完第一条打印之后,运到coroutine.yeld(),协同程序被挂起了
coroutine.resume(c)-- coroutine 2 重启协同程序,继续之前的打印,必须每打印完一条信息,手动恢复协同程序,直到打印完10条信息为止
-------------------------------------------------------------------------------
LUA协同程序当中,resume-yield可以用来传递交换信息
情况一:
1.1当协同程序主函数没有参数时,如:
c = coroutine.create(function() print 'ONE' end)
用resume时,传入除c协同对象外,还有其他参数,其他参数将被忽略。
coroutine.resume(c,xx)
1.2当协同程序主函数有参数a,b时,如:
c = coroutine.create(function(a,b) print a..'ONE' .. b end)
调用resume时传入参数a,b时,a,b被传入主函数内
情况二:
在讲之前,我们讲一下resume的返回值,resume函数采用了前面讲过的保护模式,即实现包含在pcall函数之内,所以其返回失败格式:false error info 返回成功 true + 协同主函数内return返回值,或者是yeild函数的返回值
如果协同程序主函数中调用了yield函数
2.1当yield函数有参数时,如时resume传入了多余参数,yeild的参数将被作为resume的返回值,举例如下
c = coroutine.create(function(a,b) coroutine.yeild(a+b,a*b) end)
print(coroutine.resume(c,1,2)) -- true 3,2 (说明1+2=3,1*2 =2)
2.2当yield函数没有参数时,如时resume传入了多余参数,所有多余参数将被作为resume的返回值,举例如下
c = coroutine.create(function(a,b) coroutine.yeild() end)
print(coroutine.resume(c,1,2)) -- true 1,2情况三:
协同主函数内并没有调用yeild函数,只包含return 语句时,举例如下:
c = coroutine.create(function() return "hellor" end)
print(coroutine.resume(c)) --true hellor 返回值被resume当作返回值
-------------------------------------------------------------------------------------------------------
LUA协同程序的resume-yeild机制
举例:生产者--消费者问题
生产者读出文件单词发送给消费者,消费者接收单词,并写回另一个文件当中
function producer()
while true do
local x = io.read();
send(x)
end
end
function comsumer()
while true do
local x = recevice()
io.write(x,"\n");
end
end
上面的代码当中,生产者,消费者都以我为中心,并不能分出谁是主导,谁是被调用者。二者都以自己为主导,认为对方是被调用者。
我们将代码修改如下:
让消费者启动整个生产,消费流程。
producer = coroutine.create(function()
while true do
local x = io.read();
send(x)
end
end)
function comsumer()
while true do
local x = recevice()
io.write(x,"\n");
end
end
fucntion recevice()
local status,value = corotine.resume(producer)
return value;
end
coroutine.yeild(x);
end
好了,本节讲到这里。LUA基础教程到此为止。
更多关于协同程序的应用,欢迎加入LUA交流群~~
------------------------------------------------------------------------------------------------
(1)LUA程序设计-开篇(beginning)(2012-07-28 00:47) (2)LUA程序设计-类型与值(type & value)(2012-07-28 23:12)
|
更多内容:
1LUA高级程序设计
2LUA常用库,包括string,os,math,debug等库
3LUA与C互相调用及相关API的使用。