lua 协同程序 coroutine
Lua 协同程序 coroutine
co = coroutine.create(function() print("hi") coroutine.yield() --挂起(suspended) end) coroutine.status(co) coroutine.resume(co)
Lua将所有关于协同程序的函数放置在一个名为 coroutine 的table中。函数create用于创建新的协同程序, 他只是一个参数,就是一个函数。该函数的代码就是协同程序所需要执行的内容。create会返回一个thread类型的值,用以表示新的协同程序。通常create的参数是一个匿名函数,例如:
co = coroutine.create(function() print("hi") end) print(co) -->thread:0x8071d98
一个协同程序可以出于不同的4中状态:挂起(suspended), 运行(running), 死亡(dead)和正常(normal)
当创建一个协同程序,它是出于挂起的状态。也就是说,协同程序不会再创建的时候后自动执行内容。可以同函数status来检查协同程序的状态:
print(coroutine.status(co)) -->suspended
函数coroutine.resume用于启动或再次启动一个协同程序的执行, 并将其状态改为运行:
coroutine.resume(co) -->hi
在本例中,协同程序的内容只是简单的打印hi,后便终止啦,让后他就处于死亡状态,也就再也无法返回了:
print(coroutine.status(co)) -->dead
==========================================================
协同程序的强大在于函数yield的使用上,该函数可以让一个运行中的协同程序挂起,之后可以再回复他的运行。以下是简单示例:
co = coroutine.create(function () for i=, 10 do print("co", i) coroutine.yield() --挂起(suspended) end end)
当唤醒这个协同程序时,他就会开始执行,直到第一个yield:
coroutine.resume(co) -->co 1
如果此时检查其状态,会发现协同程序处于挂起状态,因此可以再次恢复其运行:
print(coroutine.status(co)) -->suspended
...more
lua2 74页
===========================================================
转载:http://timyang.blog.51cto.com/1539170/307675
原理探析
- coroutine创建的所谓的“线程”都不是真正的操作系统的线程,实际上是通过保存stack状态来模拟的。
- 由于是假的线程,所以切换线程的开销极小,同时创建线程也是轻量级的,new_thread只是在内存新建了一个stack用于存放新coroutine的变量,也称作lua_State
LUA_API lua_State *lua_newthread (lua_State *L)
- 调用yield()当前线程交出控制权,同时还可以通过stack返回参数。调用resume的线程(可理解为主线程)获得返回的参数。
- Lua yield()和Java中的Thread.yield()有点相似,但是区别更大。Java中的yield调用后只是将当前CPU切换到另外一个线程,CPU可能随时会继续回到线程执行。
- 我更倾向于把Lua中的yield()和resume()和Java中的wait()和notify()来对比。它们表现的行为基本一致。
- 关于stack实现也可参看Yufeng(Erlang高手)的分析文章 lua coroutine是如何实现的?
===========================================================
协同程序 resume-yield
--协同程序的创建
co1 = coroutine.create(function() print("hi") end) print(co1) --thread: 0x8039288 print(coroutine.status(co1)) --suspended coroutine.resume(co1) --hi print(coroutine.status(co1)) --dead
--yield的使用
co2 = coroutine.create(function() for i=1, 10 do print("co2", i) coroutine.yield() --wait end end) coroutine.resume(co2) --1 coroutine.resume(co2) --2 coroutine.resume(co2) --3 coroutine.resume(co2) --4 coroutine.resume(co2) --5 coroutine.resume(co2) --6 coroutine.resume(co2) --7 coroutine.resume(co2) --8 coroutine.resume(co2) --9 coroutine.resume(co2) --10
--第一次调用resume时,并没有对应的yield在等待他,因此所有传递给resume的额外参数都将视为协同程序的函数的参数
co3 = coroutine.create(function(a, b, c) print("co3", a, b, c) end) coroutine.resume(co3, 1, 2, 3) --resume 传入参数
--在resume调用返回的内容中,第一个值为true表示没有错误,而后面所有的值都是对应yield传入的参数
co4 = coroutine.create(function(a, b) coroutine.yield(a+b, a-b) --yield返回参数,传入resume end) print(coroutine.resume(co4, 20, 10)) --resume 传入参数 -->true 30 10
--以此对应,yield返回的额外值就是对应resume传入的参数
co5 = coroutine.create(function() print("co5", coroutine.yield()) -- co5 4 5 end) coroutine.resume(co5) coroutine.resume(co5, 4, 5)
--最后当一个协同程序结束时,它的主函数所返回的值都将作为对应的resume的返回值
co6 = coroutine.create(function() return 6, 7 end) print(coroutine.resume(co6)) --true 6 7
-----end!!!
 
                    
                     
                    
                 
                    
                 
 
         
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号