- 0X47 同时执行
如果想让代码知道当前是哪个线程在运行自己,可以使用coroutine.running函数.这个函数会返回运行它的线程.
在线程内调用coroutine.yield函数可以阻塞线程(suspended),虽然没有执行完但是让出计算资源,把控制权交还给启动这个线程的线程.
但是存在一些状态下线程无法阻塞,为了以防万一可以使用coroutine.isyieldable函数查看当前线程是否可以阻塞(或者说挂起).如果为true则可以阻塞.一般来说只有在执行不可阻塞的的C函数或者线程是主线程时不可阻塞.(主线程涉及到Lua虚拟机机制,以后的教程中可能会涉及.)
coroutine.yield可以接受参数,它接受的参数会作为额外参数返回本次重启线程的函数调用的位置(除了额外参数,每次执行线程都会至少返回一个逻辑值表示执行是否成功).
如果线程不是第一次启动,则coroutine.resume接受的参数会返回线程中上次yield的位置.
例如:
f=function (...)
print('first',...)
print('second',coroutine.yield('yield return value'))
return 'final return value'
end
co=coroutine.create(f)
x,y=coroutine.resume(co,'hello')
print(x,y)
x,y=coroutine.resume(co,'bye')
print(x,y)
如果执行中遇到错误意外终止,coroutine.resume会返回false和错误信息.
到这里,Lua提供的线程工具就介绍完了.并不像其他语言的多线程或者多进程机制,提供了自动调度.Lua中需要我们自己通过循环来实现一个简单的同步推进.
比如让一个线程输出'hello'一百次,让另一个线程从1数到110.
cr=coroutine
f1=function ()
local i=1
while i<=100 do
print(i)
i=i+1
cr.yield()
end
end
f2=function ()
local i=1
while i<110 do
print('hello')
i=i+1
cr.yield()
end
end
co1=cr.create(f1)
co2=cr.create(f2)
repeat
cr.resume(co1)
cr.resume(co2)
until (cr.status(co1)=='dead' and cr.status(co2)=='dead')
虽然协程比一般线程来说,推进顺序更确定,更安全.但是仍然可能出现parallel或concurrent中常见的死锁等问题.解决这类问题所要进行的讨论远远超出了我们这门课的内容量.所以我可能会在别的教程中浅谈一下(也可能不谈).
虽然同步执行带来了风险,但是它提高了效率.对于有的实时控制系统来说,甚至是必不可少的.
Lua的io库中还提供了一个和同时执行有关的函数.io.popen可以用于启动一个子进程,并返回与这个进程相关的文件模型.这个函数需要系统的支持,而且涉及到系统的parallel或者concurrent机制.所以这里我们就不详细讨论了.
- 0X49 调试