Skip to content

Latest commit

 

History

History
90 lines (60 loc) · 2.8 KB

0X48线程调度.md

File metadata and controls

90 lines (60 loc) · 2.8 KB

0X48 线程调度

前置知识

  • 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和错误信息.

concurrent

到这里,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 调试