实际上,我正在使用 Visual C++ 尝试将 lua 函数绑定为套接字事件的回调(在另一个线程中)。我在一个线程中初始化 lua 的东西,而套接字在另一个线程中,所以每次套接字发送/接收消息时,它都会调用 lua 函数,而 lua 函数根据里面的“标签”确定它应该做什么信息。
所以我的问题是:
由于我将相同的 Lua 状态传递给 lua 函数,这安全吗?它不需要某种保护吗?lua 函数是从另一个 thead 调用的,所以我猜它们可能会同时被调用。
如果不安全,这种情况的解决方案是什么?
实际上,我正在使用 Visual C++ 尝试将 lua 函数绑定为套接字事件的回调(在另一个线程中)。我在一个线程中初始化 lua 的东西,而套接字在另一个线程中,所以每次套接字发送/接收消息时,它都会调用 lua 函数,而 lua 函数根据里面的“标签”确定它应该做什么信息。
所以我的问题是:
由于我将相同的 Lua 状态传递给 lua 函数,这安全吗?它不需要某种保护吗?lua 函数是从另一个 thead 调用的,所以我猜它们可能会同时被调用。
如果不安全,这种情况的解决方案是什么?
异步回调到 Lua 状态是不安全的。
有很多方法可以处理这个问题。最受欢迎的涉及某种投票。
最近的通用同步库是DarkSideSync
一个流行的 Lua 绑定到 libev 是lua-ev
这个 SO 答案推荐使用 LuaSocket 的 Lua Lanes。
在多个线程中同时调用一个 Lua 状态中的函数是不安全的。
我正在处理同样的问题,因为在我的应用程序中,通信等所有基础知识都由 C++ 处理,所有业务逻辑都在 Lua 中实现。我所做的是创建一个Lua 状态池,这些状态都是增量创建和初始化的(一旦没有足够的状态,创建一个并使用通用函数/对象进行初始化)。它是这样工作的:
我认为这种方法也非常适合您的情况。池在上次签出时检查每个状态(以间隔为基础)。当时间差足够大时,它会破坏状态以保存资源并根据当前服务器负载调整活动状态的数量。签出的状态是可用状态中最近使用的状态。
在实现这样的池时,您需要考虑一些事项:
当然,这只是一种想法,但事实证明它最适合我。
最简单的解决方案是使用lua_lock
和lua_unlock
宏使用全局锁。那将使用单个 Lua 状态,由单个互斥锁锁定。对于少量的回调它可能就足够了,但对于更高的流量它可能不会因为产生的开销。
一旦你需要更好的性能,WB 提到的 Lua 状态池是处理这个问题的好方法。这里最棘手的部分是我发现跨多个状态同步全局数据。
Doug 提到的DarkSideSync在主应用程序循环驻留在 Lua 端的情况下很有用。我为此专门写了它。在您的情况下,这似乎不合适。话说回来; 根据您的需要,您可能会考虑更改您的应用程序,以便主循环确实驻留在 Lua 端。如果你只处理套接字,那么你可以使用 LuaSocket 并且根本不需要同步。但显然这取决于应用程序还能做什么。