如何防止Lua的种族状况?

时间:2013-02-13 13:02:30

标签: multithreading lua race-condition

我正在编写一个Lua脚本,该脚本使用库来访问带有按钮的硬件设备。我注册了一个回调函数来处理按钮按下。代码如下:

globalvar = {}

function buttonCallback(buttonId)
    ...accessing globalvar
end

device.RegisterButtonCallback("buttonCallback")

while true do
end

这很有效。

现在我想更新globalvar,不仅要按下按钮,还要每隔1分钟更新一次。因为无论如何我都需要访问网络资源,我打算使用socket.select调用来获得1分钟的间隔。

#require "socket"

globalvar = {}

function buttonCallback(buttonId)
    ...access globalvar
end

device.RegisterButtonCallback("buttonCallback")

while true do
    socket.select(nil, nil, 60)  -- wait 60 seconds
    ...access network
    ...access globalvar
end

现在我担心globalvar的并发访问。我怎样才能防止这里的竞争条件? Lua中关于多线程的大多数消息来源都建议在协作调度中使用continuation,但我不知道如何在我的情况下应用它。

3 个答案:

答案 0 :(得分:2)

假设您正在使用的库是在幕后创建另一个线程,而您唯一关心的是从回调中访问globalvar,您可以通过写入回调中的管道并阅读来避免它在你的select循环中来自它。换句话说,使用标准POSIX样式的管道将回调传递回主线程。处理例如,这是一种相当常见的技术。 POSIX信号。

答案 1 :(得分:2)

Lua在特定lua_State实例中不是线程安全的。您无法从一个线程修改全局变量,而另一个线程正在使用该Lua实例执行其他操作。你当然不能在同一个实例上执行两个单独的脚本。

线程安全是你在Lua之外必须做的事情。你不能让检测按钮的C / C ++线程实际上直接调用Lua代码。它必须通过一些线程安全机制将数据发送到主线程,其中 it 将为它们调用Lua脚本。

答案 2 :(得分:0)

所以我深入研究了Lua书籍和在线文档,并联系了设备驱动程序的作者。正如已经指出的答案,安全地处理按钮回调需要比预期更多。

我现在的方法是自己编写设备驱动程序,并使用套接字作为设备和Lua脚本之间的通信通道。

我最初的方法是使用continuation,因为这被称为多线程的Lua“替换”但是当我在Lua书中阅读编程时,事实证明为了防止繁忙的等待,它使用了socket.select( !)。这增加了我对基于套接字的方法很好的感觉,特别是因为我的脚本中还需要用于访问Internet的套接字。