Lua 协程的用途是什么?为什么这段代码不能按我的预期工作?
我在理解这段代码时遇到了困难...我期待类似线程的东西,我会得到一个随机的“nooo”和“yaaaay”的输出,因为它们都是异步打印的,但我发现主线程似乎在第一次调用 coroutine.resume() 时阻塞,从而阻止下一个线程启动,直到第一个线程产生为止。
如果这是预期的操作协程,它们有什么用处,以及我将如何实现我希望的目标?我是否必须实现自己的调度程序才能使这些协程异步操作?因为这看起来很混乱,而且我也可以使用函数!
co1 = coroutine.create(function ()
local i = 1
while i < 200 do
print("nooo")
i = i + 1
end
coroutine.yield()
end)
co2 = coroutine.create(function ()
local i = 1
while i < 200 do
print("yaaaay")
i = i + 1
end
coroutine.yield()
end)
coroutine.resume(co1)
coroutine.resume(co2)
I'm having trouble understanding this code... I was expecting something similar to threading where I would get an output with random "nooo" and "yaaaay"s interspersed with each other as they both do the printing asynchronously, but rather I discovered that the main thread seems to block on the first calling of coroutine.resume() and thus prevents the next from being started until the first has yielded.
If this is the intended operation coroutines, what are they useful for, and how would I achieve the goal I was hoping for? Would I have to implement my own scheduler for these coroutines to operate asynchronously?, because that seems messy, and I may as well use functions!
co1 = coroutine.create(function ()
local i = 1
while i < 200 do
print("nooo")
i = i + 1
end
coroutine.yield()
end)
co2 = coroutine.create(function ()
local i = 1
while i < 200 do
print("yaaaay")
i = i + 1
end
coroutine.yield()
end)
coroutine.resume(co1)
coroutine.resume(co2)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
协程不是线程。
协程就像从不主动调度的线程。所以是的,你是正确的,你必须编写自己的调度程序才能让两个协程同时运行。
然而,当涉及到协程时,您会错过更大的图景。查看维基百科的协程使用列表。这是一个可能引导您走向正确方向的具体示例。
可以将上面的脚本编写为使用 switch 语句和一些巧妙的状态变量来迭代运行。但写成协程就清晰多了。上面的脚本可以是一个线程,但是您真的需要将内核线程专用于这个简单的代码吗?繁忙的游戏关卡可能会运行 100 个这样的协程,而不会影响性能。然而,如果每个线程都是一个线程,那么在性能开始受到影响之前,您可能可以使用 20-30 个线程。
协程旨在允许我编写在堆栈上存储状态的代码,以便我可以停止运行它一段时间(
wait
函数)并在我停止的地方重新启动它。Coroutines aren't threads.
Coroutines are like threads that are never actively scheduled. So yes you are kinda correct that you would have to write you own scheduler to have both coroutines run simultaneously.
However you are missing the bigger picture when it comes to coroutines. Check out wikipedia's list of coroutine uses. Here is one concrete example that might guide you in the right direction.
The above script could be written to run iteratively with a switch statement and some clever state variables. But it is much more clear when written as a coroutine. The above script could be a thread but do you really need to dedicate a kernel thread to this simple code. A busy game level could have 100's of these coroutines running without impacting performance. However if each of these were a thread you might get away with 20-30 before performance started to suffer.
A coroutine is meant to allow me to write code that stores state on the stack so that I can stop running it for a while (the
wait
functions) and start it again where I left off.由于有许多评论询问如何实现
wait
函数以使deft_code
的示例正常工作,因此我决定编写一个可能的实现。总体思路是,我们有一个包含协程列表的调度程序,调度程序决定在协程通过wait
调用放弃控制后何时将控制权返回给协程。这是可取的,因为它使异步代码可读且易于推理。这只是协程的一种可能用途,它们是一种更通用的抽象工具,可用于许多不同的目的(例如编写迭代器和生成器、编写有状态流处理对象(例如解析器中的多个阶段)、实现异常)和延续等)。
首先:调度程序定义:
现在,初始化世界:
游戏的(虚拟)接口:
以及游戏循环:
Since there have been a number of comments asking how to implement the
wait
function that would makedeft_code
's example work, I've decided to write a possible implementation. The general idea is that we have a scheduler with a list of coroutines, and the scheduler decides when to return control to the coroutines after they give up control with theirwait
calls. This is desirable because it makes asynchronous code be readable and easy to reason about.This is only one possible use of coroutines, they are a more general abstraction tool that can be used for many different purposes (such as writing iterators and generators, writing stateful stream processing objects (for example, multiple stages in a parser), implementing exceptions and continuations, etc.).
First: the scheduler definition:
Now, initialising the world:
The (dummy) interface to the game:
And the game loop: