从另一个线程调用一个lua函数(作为回调函数)是否足够安全?

其实我正在使用Visual C ++尝试将lua函数绑定为套接字事件(在另一个线程中)的回调。 我在一个线程中初始化了lua的东西,并且套接字在另一个线程中,所以每当套接字发送/接收到一条消息时,它都会调用lua函数,并且lua函数根据函数中的'tag'确定它应该做什么信息。

所以我的问题是:

  • 既然我把同一个Lua国家通过lua职能,那安全吗? 它不需要一些保护? lua函数是从另一个thead调用的,所以我猜他们可能会被同时调用。

  • 如果不安全,这种情况的解决方案是什么?


  • 异步回调到Lua状态是不安全的。

    有很多方法可以解决这个问题。 最受欢迎涉及某种投票。

    最近的通用同步库是DarkSideSync

    流行的Lua绑定到libev是lua-ev

    这个SO回答建议LuaSocket与LuaSocket。


  • 在多个线程中同时调用一个Lua状态的函数是不安全的。

  • 我正在处理同样的问题,因为在我的应用程序中,所有基础(如通信)都由C ++处理,所有业务逻辑都在Lua中实现。 我所做的就是创建一个Lua状态池,这些状态都是以增量方式创建和初始化的(一旦没有足够的状态,创建一个并使用通用函数/对象进行初始化)。 它是这样工作的:

  • 一旦连接线程需要调用一个Lua函数,它会检出Lua状态的一个实例,在独立的(代理)全局表中初始化特定的全局变量(我称之为线程/连接上下文),以防止污染原始全局变量,但是由原始全球索引
  • 调用一个Lua函数
  • 检查Lua状态返回到池中,在那里它恢复到“就绪”状态(处理代理全局表)
  • 我认为这种方法也适合你的情况。 池会检查每个状态(以间隔为基础)何时最后一次检出。 当时间差足够大时,它会销毁状态以保留资源并将活动状态的数量调整为当前的服务器负载。 检出的状态是可用状态中最近使用的状态。

    在实施这样一个池时,你需要考虑一些事情:

  • 每个状态需要填充相同的变量和全局函数,这会增加内存消耗。
  • 实现池中状态计数的上限
  • 确保每个状态中的所有全局变量处于一致状态,如果它们发生变化(这里我建议只预先填充静态全局变量,而在检查状态时填充动态变量)
  • 动态加载函数。 在我的情况下,有成千上万的函数/过程可以在Lua中调用。 让他们不断加载到所有的州将是一个巨大的浪费。 因此,我保留它们在C ++端编译的字节码,并在需要时加载它们。 事实证明,在我的情况下不会影响性能,但是你的里程可能会有所不同。 要记住的一件事是只加载一次。 假设您调用需要在循环中调用另一个动态加载函数的脚本。 然后你应该在循环之前把函数加载一次。 否则会造成巨大的性能下降。
  • 当然,这只是一个想法,但却是最适合我的想法。


  • 像其他人提到的那样,这并不安全
  • 取决于你的用例
  • 最简单的解决方案是使用lua_locklua_unlock宏使用全局锁。 这将使用单个互斥体锁定的单个Lua状态。 对于少量的回调可能就足够了,但对于更高的流量,可能不会由于发生的开销。

    一旦你需要更好的表现,世界银行提到的Lua国家游泳池是处理这个问题的好方法。 这里最棘手的部分是我发现跨多个状态同步全局数据。

    Doug提到的DarkSideSync在主应用程序循环驻留在Lua端的情况下非常有用。 我专门为此写了它。 在你的情况下,这似乎不适合。 话说回来; 根据您的需要,您可能会考虑更改您的应用程序,以便主循环驻留在Lua端。 如果你只处理套接字,那么你可以使用LuaSocket并且根本不需要同步。 但显然这取决于应用程序的其他功能。

    链接地址: http://www.djcxy.com/p/71501.html

    上一篇: Is calling a lua function(as a callback) from another thread safe enough?

    下一篇: how to detect the Page Close Event with ASP.NET