Lua 的多线程支持

栏目: Lua · 发布时间: 6年前

内容简介:单个 Lua 虚拟机只能工作在一个线程下,如果你需要在同一个进程中让 Lua 并行处理一些事务,必须为每个线程部署独立的 Lua 虚拟机。ps. 在少量多线程应用环境,加锁也是可行的。你可以在编译时自定义比较成熟的 lua 多线程库有

单个 Lua 虚拟机只能工作在一个线程下,如果你需要在同一个进程中让 Lua 并行处理一些事务,必须为每个线程部署独立的 Lua 虚拟机。

ps. 在少量多线程应用环境,加锁也是可行的。你可以在编译时自定义 lua_lock(L)lua_unlock(L) 去调用操作系统的锁。

比较成熟的 lua 多线程库有 LanesEffil 。它们都试图隐藏多虚拟机的细节,让用户使用起来好像多线程在使用同一个虚拟机一样。比如 Effil 就用了 effil.table 去模拟 table 并让多个虚拟机可以共享数据;Lanes 则有 deep userdata 可以在不同线程间共享。

这些个方案都允许用户在不同的虚拟机间相互调用函数,大约是利用在虚拟机间同步函数的字节码和 upvalue 实现的。基于这些线程库的程序,用起来和别的支持多线程的语言(比如 Golang)那样没有太大区别。

但我不喜欢这种多线程解决方案。我认为多线程本身是复杂的,隐藏线程并行运行的细节,让用户基于共享状态去写程序并没有什么好处。如果阅读代码的人一眼看上去并不能立刻分辨出一个函数到底会在哪个线程运行,只会增加多线程程序的维护成本。

所以,skynet 采用的是让框架去支持多线程,让用户明确知道有独立的虚拟机的概念,以及它们跑在不同的线程下。只用消息队列来协同工作。还有很多类似的项目也是这样做的,比如 cqueues

我最近在开发客户端引擎时也遇到了多线程问题。例如 bgfx 的 log 回调就可能发生在不同线程中,所以无法简单的封装成 lua 函数进行回调;我们的引擎需要通过网络加载资源/代码,这部分网络 IO 处理最好能和逻辑线程分离,等等。

一开始,我采用的是 Lanes 。但是做了一段时间后,我觉得滥用多线程很容易滋生 bug 。

最近,我希望去掉 Lanes 这个库,改用自己实现的一套最简的线程库。由于客户端线程数量比较固定,无非是渲染线程,逻辑线程,IO 线程,Lua 调试器线程,物理线程;线程之间有固定的消息管道交换数据就够了。

所以,我想我可以从最基本的线程 api 设计起,一点点按需完善这个线程库。一开始,只需要有线程的创建;通讯管道可以支持收发 lua 基础数据类型就可用了。这部分在 skynet 中已经非常稳定,只需要把代码搬过来。

由于图形客户端有天然的运行周期(按帧渲染),我甚至不需要给通讯管道加读取超时参数。只用周期性查询是否有新数据即可。通讯管道也是有限的,所以并不需要像 golang 那样把 channel 做成 first class 的类型,并支持自由创建和销毁。我可以支持有限数量的具名管道,不同线程间约定好名字就可以通讯。

这些基础设施实现出来比我想象的要简单。搬运一些老代码,添加好 lua 的封装,一个周末就完成了。下周可以基于它们来重构我们已经做好(但还有 bug )的引擎代码。


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

UML风格

UML风格

布格勒 / 袁峰 / 2008-12 / 35.00元

《UML风格(第2版)(英汉对照)》给出了一系列有效提高团队生产效率的编程风格的原则,描述了创建简洁、易于理解的UML图的标准和指南,涉及类图、定时图、用例图、组合结构图、顺序图、交互概览图、活动图、对象图、状态图、包图、通信图、部署图和组件图等内容。著名UML专家Scott W.Ambler描述了创建UML图的标准和指南,以帮助建模人员创建简明而易于理解的UML 图形。 《UML风格(第2......一起来看看 《UML风格》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

正则表达式在线测试
正则表达式在线测试

正则表达式在线测试