Lua学习——Coroutine协程

在菜鸟教程学习lua时,在coroutine这一章看到这么一段

coroutine.running就可以看出来,coroutine在底层实现就是一个线程。

当create一个coroutine的时候就是在新线程中注册了一个事件。

当使用resume触发事件的时候,create的coroutine函数就被执行了,当遇到yield的时候就代表挂起当前线程,等候再次resume触发事件。

对此感到十分困惑,因为在unity中的协程是在主线程中执行的,在我看来既然叫协程不叫线程那就明显是跟线程的原理是不一样的,更重要的是在这一段代码中

function foo (a)
    print("foo 函数输出", a)
    return coroutine.yield(2 * a) -- 返回  2*a 的值
end
 
co = coroutine.create(function (a , b)
    print("第一次协同程序执行输出", a, b) -- co-body 1 10
    local r = foo(a + 1)
     
    print("第二次协同程序执行输出", r)
    local r, s = coroutine.yield(a + b, a - b)  -- a,b的值为第一次调用协同程序时传入
     
    print("第三次协同程序执行输出", r, s)
    return b, "结束协同程序"                   -- b的值为第二次调用协同程序时传入
end)
        
print("main", coroutine.resume(co, 1, 10)) -- true, 4
print("--分割线----")
print("main", coroutine.resume(co, "r")) -- true 11 -9
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- true 10 end
print("---分割线---")
print("main", coroutine.resume(co, "x", "y")) -- cannot resume dead coroutine
print("---分割线---")

coroutine.resume()的执行必然会阻塞主线程,这从逻辑上说不通,我也进行测试过

在网上看了其他人的分析更确定了我的结论。

所以我认为,lua的coroutine跟unity一样都是在主线程执行的,只是它特别维护了一块独立的内存,用以实现对同一段代码进行断续的执行。

另外,coroutine.running()这个方法在主线程调用的时候是无法获得当前协程的id的,以为此时协程并没有执行(因为协程是在主线程执行的,此时已被挂起或销毁)。只有在协程的代码块中才能正确获取当前的协程id,在主线程中调用时候应该获得的是主线程id(有待商榷,测试时候主线程获得的id是固定的,而在协程中获得的id是随协程切换而变化的)

//////////////////////////////////////////////////////////////////

关于coroutine.resume的参数问题。

当coroutine  被create后,第一次调用resume传递的方法的初始化参数这里没问题。

但是第二次以及以后穿的参数又是何物,这里必须提到coroutine的中断位置问题,参考上方代码

有这么一句 

 local r, s = coroutine.yield(a + b, a - b)  -- ab的值为第一次调用协同程序时传入

当调用yield时候协程会挂起交由主程序执行等待下次resume

注意,挂起时这一句并没有执行完毕只是执行了yield并挂起协程交由主程序执行(这也是以上所说的阻塞),当下次resume后才会return,并继续左边的赋值操作。

所以yield中的两个参数会在挂起协程后在返回给主程序,并通过resume来return,让主程序获得到coroutine的执行结果。

同理下一次的resume传入的参数会在协程被再次唤醒后,继续执行yield的return并作为参数向左侧赋值。

yield的参数是向外通信的入口,resume的返回是向外通信的出口

 resume的参数是向内通信的入口,yield返回时向内通信的出口。



你可能感兴趣的:(lua学习)