标签:
协同程序与线程差不多,也就是一条执行序列,拥有自己独立的栈、局部变量和指令指针,同时又跟其他协同程序共享全局变量和其他大部分东西。从概念上来讲,线程与协同程序的主要区别在于:一个具有多线程的程序可以同时运行几个线程,而协同程序却需要彼此协作的运行。就是说,一个具有多个协同程序的程序在任意时刻只能运行一个协同程序,并且正在运行的协同程序只会在其显示的要求挂起时,它的执行才会暂停。
lua将所有关于协同程序的函数放置在一个名为“coroutine”的table中,函数create用于创建新的血统程序,它只有一个参数,就是一个函数。该函数的代码就是协同程序需要执行的内容。create会返回一个thread类型的值,用于表示新的协同程序,一般create的参数是一个匿名函数,如:
local co = coroutine.create(function() print("hi) end)
一个协同程序有四种不同的状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。当新创建一个协同程序时,它处于挂起状态,也就是说,协同程序不会在创建它的时候自动运行。我们可以通过函数status来检查协同程序的状态。
local co = coroutine.create(function() print("hi") end) print(coroutine.status(co)) --suspended
函数coroutine.resume用于启动或再次启动一个协同程序的执行,并将其状态由挂起改为运行。
local co = coroutine.create(function() print("hi") end) print(coroutine.status(co)) --suspended coroutine.resume(co) --hi
上面的代码中调用来resume函数,将协同程序co由suspended改为running状态,当打印了hi之后,co就处于死亡状态了。
我们现在来看一下协程函数的yield,该函数可以让一个运行中的协同程序挂起,而之后可以再恢复它的运行。看下面的例子:
local co = coroutine.create(function() for i=1,5 do print(i) coroutine.yield() end end) print(coroutine.status(co)) coroutine.resume(co) print(coroutine.status(co)) coroutine.resume(co) print(coroutine.status(co)) coroutine.resume(co) coroutine.resume(co) coroutine.resume(co) --coroutine.resume(co)注意这句话 print(coroutine.status(co)) coroutine.resume(co)
输出:
suspended 1 suspended 2 suspended 3 4 5 suspended --当把上面的注释打开,这是输出为:dead
在最后一次调用resume时,协同程序的内容已经执行完毕,并已经返回。因此,这时协同程序处于死亡状态。当在协同程序的执行中发生任何错误,Lua是不会显示错误消息的,而是将执行权返回给resume调用。当coroutine.resume的第一个返回值为false时,就表明协同程序在运行过程中发生了错误;当值为true时,则表明协同程序运行正常。
当一个协同程序A唤醒另一个协同程序B时,协同程序A就处于一个特殊状态,既不是挂起状态(无法继续A的执行),也不是运行状态(是B在运行)。所以将这时的状态称为“正常”状态。
Lua的协同程序还具有一项有用的机制,就是可以通过一对resume-yield来交换数据。在第一次调用resume时,并没有对应的yield在等待它,因此所有传递给resume的额外参数都视为协同程序主函数的参数。
当协同程序中没有yield时,第一次调用resume,所有传递给resume的额外参数都将视为协同程序主函数的参数,如以下代码:
local co = coroutine.create(function (a, b, c) print("co", a, b, c) end) coroutine.resume(co, 1, 2, 3) -- co 1 2 3
在resume调用返回的内容中,第一个值为 true则表示没有错误,而后面所有的值都是对影yield传入的参数:
local co = coroutine.create(function(a,b) coroutine.yield(a+b,a-b) end) print(coroutine.resume(co,20,10))
输出:
true 30 10
于此对应的时,yield返回的额外值就是对应resume传入的参数:
local co = coroutine.create(function() print(coroutine.yield()) end) coroutine.resume(co) coroutine.resume(co,4,5)
输出:
4
最后,当一个协同程序结束时,它的主函数所返回的值都将作为对应resume的返回值:
local co = coroutine.create(function() return 6,7 end) print(coroutine.resume(co))
输出:
true 6
标签:
原文地址:http://my.oschina.net/u/815187/blog/485109