从另一个线程调用Lua函数(作为回调)是否足够安全?
实际上我正在使用 Visual C++ 尝试将 Lua 函数绑定为套接字事件的回调函数(在另一个线程中)。我在一个线程中初始化 Lua,而套接字在另一个线程中,所以每次套接字发送/接收消息时,它将调用 Lua 函数,Lua 函数根据消息中的“标签”确定它应该做什么。
所以我的问题是:
由于我将相同的 Lua 状态传递给 Lua 函数,这是安全的吗?它不需要某种保护吗?Lua 函数是从另一个线程中调用的,所以我猜它们可能会同时被调用。
如果这是不安全的,这种情况的解决方案是什么?
在多个线程中同时调用同一个 Lua 状态下的函数是不安全的。
我之前也遇到过这个问题,因为我的应用程序中所有基础功能如通信都是由 C++ 处理完成的,而所有业务逻辑都是在 Lua 中实现的。我的解决方案是创建一个 Lua 状态池,这些状态在逐步创建和初始化(一旦没有足够的状态,就创建一个并用公共函数 / 对象进行初始化)。具体实现方法如下:
- 当连接线程需要调用 Lua 函数时,它会检出一个 Lua 状态的实例,并在一个单独的 (代理) 全局表中初始化特定的全局变量(我称之为线程 / 连接上下文),以防止污染原始全局变量,但是它的索引是原始全局变量
- 调用 Lua 函数
- 将 Lua 状态检入池中,其中它会恢复到“就绪”状态(释放代理全局表)
我认为这种方法也很适合您的情况。池会定期检查每个状态的最后一次检出时间,当时间差足够大时,它会销毁状态以保留资源并调整当前服务器负载下的活动状态数量。已检出的状态是可用状态中最近使用的状态。
在实现这样一个池时,需要考虑以下几点:
- 每个状态需要填充相同的变量和全局函数,这会增加内存消耗。
- 为池中状态数量实现上限
- 确保每个状态中的所有全局变量处于一致状态,如果它们发生变化(我建议仅预填静态全局变量,而在检出状态时填充动态变量)
- 动态地加载函数。在我的情况下,有成千上万的函数 / 过程可以在 Lua 中调用。将它们常驻内存对资源来说是一种巨大浪费。因此,我将它们编译成字节码并在需要时加载。在我的情况下,它并不会对性能产生太大的影响,但是您的情况可能会有所不同。需要记住的一件事是仅加载一次。举个例子,假设您在循环中调用一个需要调用另一个动态加载函数的脚本。那么您应该首先将该函数作为本地函数在循环之前加载。否则,这将是一个巨大的性能损失。
当然,这仅仅是一个想法,但是对我来说是最合适的一个。
- 这是不安全的,正如其他人所提到的一样。
- 取决于您的用例。
最简单的解决方案是使用 lua_lock 和 lua_unlock 宏来使用全局锁。这将使用单个被单个互斥锁上锁的 Lua 状态。对于较少的回调,可能足够,但对于更高的流量可能就不行了,因为会产生开销。
一旦您需要更好的性能,W.B. 提到的 Lua 状态池是一个不错的处理方法。我发现最棘手的部分是在多个状态之间同步全局数据。
Doug提到的 DarkSideSync 在主应用程序循环位于 Lua 端的情况下非常有用。我特别为此编写了它。在您的情况下似乎并不适合。话虽如此,根据您的需求,您可以考虑更改应用程序,使主循环确实位于 Lua 端。如果您只处理套接字,则可以使用 LuaSocket,根本不需要同步。但是,这显然取决于应用程序的其他内容。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
不安全的异步回调
在 Lua 状态中异步回调是不安全的。
有许多方法可以解决这个问题。最流行的方法是使用某种轮询。
一个最近的通用同步库是 DarkSideSync。
一个流行的 Lua 绑定库是 lua-ev。
这个 SO 回答 推荐使用带有 LuaSocket 的 Lua Lanes。