协同程序与线程差很少,也就是一条执行序列,拥有本身独立的栈、局部变量和指令指针,同时又跟其余协同程序共享全局变量和其余大部分东西。从概念上来说,线程与协同程序的主要区别在于:一个具备多线程的程序能够同时运行几个线程,而协同程序却须要彼此协做的运行。就是说,一个具备多个协同程序的程序在任意时刻只能运行一个协同程序,而且正在运行的协同程序只会在其显示的要求挂起时,它的执行才会暂停。
多线程
lua将全部关于协同程序的函数放置在一个名为“coroutine”的table中,函数create用于建立新的血统程序,它只有一个参数,就是一个函数。该函数的代码就是协同程序须要执行的内容。create会返回一个thread类型的值,用于表示新的协同程序,通常create的参数是一个匿名函数,如:
函数
local co = coroutine.create(function() print("hi) end)
一个协同程序有四种不一样的状态:挂起(suspended)、运行(running)、死亡(dead)和正常(normal)。当新建立一个协同程序时,它处于挂起状态,也就是说,协同程序不会在建立它的时候自动运行。咱们能够经过函数status来检查协同程序的状态。lua
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,该函数可让一个运行中的协同程序挂起,而以后能够再恢复它的运行。看下面的例子:code
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)
输出:orm
suspended 1 suspended 2 suspended 3 4 5 suspended --当把上面的注释打开,这是输出为:dead
在最后一次调用resume时,协同程序的内容已经执行完毕,并已经返回。所以,这时协同程序处于死亡状态。当在协同程序的执行中发生任何错误,Lua是不会显示错误消息的,而是将执行权返回给resume调用。当coroutine.resume的第一个返回值为false时,就代表协同程序在运行过程当中发生了错误;当值为true时,则代表协同程序运行正常。协程
当一个协同程序A唤醒另外一个协同程序B时,协同程序A就处于一个特殊状态,既不是挂起状态(没法继续A的执行),也不是运行状态(是B在运行)。因此将这时的状态称为“正常”状态。io
Lua的协同程序还具备一项有用的机制,就是能够经过一对resume-yield来交换数据。在第一次调用resume时,并无对应的yield在等待它,所以全部传递给resume的额外参数都视为协同程序主函数的参数。table
当协同程序中没有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 5
最后,当一个协同程序结束时,它的主函数所返回的值都将做为对应resume的返回值:
local co = coroutine.create(function() return 6,7 end) print(coroutine.resume(co))
输出:
true 6 7