浅谈Lua协程 [ 奔跑的蜗牛 ]
撰写于 2018-05-09
<span id="post-title-updated">修改于 2018-05-10</span>
</p>
<p>很多脚本语言都有线程的概念,lua也不例外,但是lua的线程有点特殊,不能算作是真正的线程,叫做协程(coroutine),一般意义上的线程有如下特征:每个线程都有自己的堆栈;可以同时执行(多核);抢占式执行,无须手动唤醒。但是协程不一样。</p>
协程特点
- 有自己的的堆栈和局部变量
- 需要手动切换协程之间的执行
- 同一时刻只能有一个协程执行(无论是否是多核)
coroutine库
coroutine.create(f)
传递一个函数f,创建一个协程,返回协程句柄。coroutine.isyieldable()
正在运行的协程是否可以让出,如果可以,返回true,只有主协程和C函数是无法让出的。coroutine.resume(co, [val1,…])
启动或者再次启动一个协程,由挂起状态(suspended)变为运行状态(running)
注:
首次启动协程会把参数[val1,…],传递给协程co的函数;
再次启动协程会把参数[val1,…],作为给协程co上一次yeild的返回值。
返回值:- 如果协程co的函数执行完毕,则协程正常终止,resume返回true和函数的返回值
- 如果协程执行过程中,协程挂起了,即调用yeild(),resume返回true和调用yeild传入的参数
- 如果协程执行过程中发生了错误,resume返回false和错误消息
coroutine.yeild(…)
使正在实行的协程挂起
注:
传递给yeild的参数会作为resume的额外返回值coroutine.running()
判断当前线程是不是主线程,如果是,返回truecoroutine.status(co)
返回string,表示协程co的状态- running:由于当前只能有一个协程在执行,只有在协程的函数中使用status,传入自身句柄,执行到此处才会返回true,作用不大
- suspended:如果协程创建了还没有执行或者调用了yeild,则返回该状态
- normal:在协程A的函数里面resume了协程B,在B的执行过程中,则A就是normal状态。此时A的状态既不是运行,也不是挂起
- dead:协程在执行过程中发生了错误,或者正常执行完毕,就是dead状态。调用resume返回false和错误消息。
coroutine.wrap(f)
这个就是一个语法糖。功能同coroutine.create(f)。但是不返回协程的句柄,而是返回了一个函数。- 每次调用返回的函数,就相当于调用了coroutine.resume()
- 如果该协程的函数执行错误,不会像resume一样,在保护模式下进行,返回false,而是直接崩溃,向外跑出异常。
以上都是摘自https://www.cnblogs.com/zrtqsk/p/4374360.html
协程的优点
通过以上的介绍可以发现,lua的协程很简单,由于是手动控制协程的切换,不用考虑因资源抢占引起的问题。
协程的缺点
因为同一时间只有一个协程拥有执行权,只相当于单线程的能力,也导致了时间片不能公平分享,很是鸡肋,功能上也跟callback有重复。而且不能跨c函数切换协程。总之线程是系统级实现,而协程只是在应用层实现。
还是不能理解协程的真谛!或许真的很强大,我不能理解!