【问题标题】:Multithreading in LuaLua 中的多线程
【发布时间】:2012-02-10 10:48:51
【问题描述】:

前几天我正在和我的朋友讨论。我说的是,在纯 Lua 中,你无法构建一个抢占式多任务系统。他声称你可以,原因如下:

C 和 Lua 都没有内置的线程库 [OP 注释:嗯,Lua 在技术上是有的,但 AFAIK 对我们的目的没有用处]。主要用 C(++) 编写的 Windows 具有先发制人的多任务处理能力,这是他们从头开始构建的。因此,您应该能够在 Lua 中做同样的事情。 我看到的一个大问题是抢占式多任务处理的主要工作方式(据我所知)是它会生成定期中断,管理器使用这些中断来获得控制并确定接下来应该处理哪些代码。我也不认为 Lua 有任何工具可以做到这一点。

我的问题是:是否有可能编写一个纯 Lua 库来让人们进行抢先式多任务处理?

【问题讨论】:

  • 仅供参考,这不是您问题的答案(多线程的纯 Lua 实现),但对于只想运行 Lue 代码多个 OS 线程并抢先调度它们的人来说,有很多选择:@ 987654321@

标签: multithreading lua preemptive


【解决方案1】:

我不知道该怎么做,虽然没有 Lua 的正式语义(例如 yield 的语义),但很难想出一个铁定的论据为什么它不能完成。 (我一直想要 ages 的正式语义,但显然 Roberto 和 lhf 有更好的事情要做。)

如果我想要 Lua 的抢先式多任务处理,我什至不会尝试在纯 Lua 中实现。相反,我会使用我 20 年前在新泽西标准 ML 中第一次看到的旧技巧:

  • 中断在lua_State 中设置一个标志,表示“当前协程已被抢占”。

  • 更改 VM,以便在每个循环和每个函数调用中,它都会检查标志并在必要时生成。

此补丁易于编写和维护。它并没有解决无法被抢占的长时间运行的 C 函数的问题,但是如果你必须解决这个问题,你就会陷入更难的领域,你不妨在C 级别,而不是 Lua 级别。

【讨论】:

  • "更改虚拟机,以便在每个循环和每个函数调用中,它都会检查标志并在必要时生成。"我们当时在使用同样不是抢占式的 Smalltalk 的第一个版本进行开发时就这样做了。发生的事情是地狱爆发了。突然之间,收益率发生在之前没有发生的时候。这导致许多互斥区域未正确同步以运行上下文切换并创建陈旧数据。也许LuaJ继承了Java中的抢占式多线程?
【解决方案2】:

没有。用纯 Lua 编写抢占式调度器是不可能的。在某些时候,抢占式调度程序需要某种机制,例如中断服务例程,以从当前线程中获取控制权并将其交给调度程序,然后调度程序可以将其交给另一个线程。纯 Lua 没有这种机制。

您提到 Windows 主要是用 C/C++ 编写的。主要是关键词。您不能在纯 ANSI C/C++ 中编写抢占式调度程序。通常,中断服务程序的一部分是用汇编语言编写的。或者,C/C++ 编译器实现了一个非标准扩展,允许用 C/C++ 编写中断服务例程。一些编译器允许您使用 __interrupt 修饰符声明函数,该修饰符会导致编译器生成延长/结语,从而允许将函数用作中断服务例程。

此外,设置中断服务例程的代码会使用内存映射 IO 或 IO 指令来处理 CPU 寄存器。这些代码都不是可移植的 ANSI C/C++。而且,取决于 CPU 架构。

【讨论】:

    【解决方案3】:

    据我所知,没有。如果你可以使用 debug.sethook 从协程上设置的钩子中产生,这几乎是荒谬的简单,但它不起作用。您可以从 C (lua_sethook) 中设置的 C 钩子中产生,但我无法完全弄清楚这样做,而且它也不是纯粹的 Lua。

    即使有可能,它也不是真正的线程。例如,一切仍将在同一个操作系统线程中运行。你的钩子会考虑多种因素(比如时间,也许是内存等),然后决定是否让步。然后,yield-to 协程将决定接下来运行哪个子协程。您还需要决定何时调用钩子。最常见的是每条 Lua 指令,但这会带来性能损失。而如果协程调用了一个 C 函数,Lua 没有管辖权。如果那个 C 调用需要很长时间,你就无能为力了。

    Here 是 Lua-L 邮件列表中的一个相关线程,您可能会觉得有趣。

    【讨论】:

    • Supreme Commander 使用了这样一个“假”线程系统,尽管我认为它对 lua 进行了自定义调整。这就是激发这个问题的原因:)
    • 坦率地说,我喜欢能够做这种事情。这会让我遇到的一些问题更容易妥善处理。
    猜你喜欢
    • 2018-03-08
    • 1970-01-01
    • 2016-09-01
    • 2017-12-09
    • 2015-06-04
    • 2021-09-01
    • 1970-01-01
    • 2015-12-06
    • 2011-01-12
    相关资源
    最近更新 更多