Lua协同程序函数coroutine使用实例
协程是协同程序的简称,顾名思义,就是协同工作的程序。协程拥有自己独立的桟、局部变量和PC计数器,同时又与其他协同程序共享全局变量和其他大部分东西;
协程与线程的主要区别在于,一个多线程程序可以同时运行几个线程(并发执行、抢占),而协同程序却需要彼此协作地运行,即一个多协程程序在任意时刻只能运行一个协程,并且正在执行的协程只会在其显式地要求挂起(suspend)时,它的执行才会暂停(无抢占、无并发)。
Lua中所有与协程相关的函数都在coroutine(一个table)中;函数create用于创建新的协程,只有一个参数——要执行的函数,返回一个thread类型的值。
thread的状态:suspend、running、dead、normal,可以通过coroutine.status(co)来检查co的状态。
创建一个thread时,它处于挂起状态。coroutine.resume函数用于启动或再次启动一个协程的执行,并可以向coroutine传递参数。当一个协程结束时,主函数返回的值将作为resume的返回值。
coroutine.yield用于一个运行中的协程挂起(suspend),之后可以再恢复(resume)。yield的返回值就是resume传入的参数。
Lua的协程模型可以类比Python的generator。
一个简单的示例:
>co=coroutine.create(function(a)whilea>0doprint(coroutine.yield(a));a=a-1;endreturn-1end) >returncoroutine.resume(co,3)---3是传递给主函数的 true 3 >returncoroutine.resume(co,4) 4 true 2 >returncoroutine.resume(co,5) 5 true 1 >returncoroutine.resume(co,6) 6 true -1---主函数已经返回 >returncoroutine.resume(co,7) false cannotresumedeadcoroutine >
协程的应用——生产者/消费者
需求:输入一行,打印一行
functionsend(x) coroutine.yield(x) end functionreceive(co) locals,v=coroutine.resume(co) returnv end functionproducer() returncoroutine.create(function() whiletruedo localx=io.read() send(x) end end) end functionfilter(prod) returncoroutine.create(function() forline=1,math.hugedo localx=receive(prod) x=string.format('%5d%s',line,x) send(x) end end) end functionconsumer(prod) whiletruedo localx=receive(prod) io.write(x,'\n') end end prod=producer() fil=filter(prod) con=consumer(fil)
协程的应用——迭代器(类比PythonGenerator)
functionseq_generator(n) locali=1 whilei<=ndo coroutine.yield(i) i=i+1 end returnnil end functionseq(n) localco=coroutine.create(function()seq_generator(n)end) returnfunction() locals,v=coroutine.resume(co) returnv end end foriinseq(4)do print(i) end
执行
luaseq_generator.lua 1 2 3 4