如何在Lua中防止竞态条件?

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

globalvar = {}

function buttonCallback(buttonId)
    ...访问 globalvar
end

device.RegisterButtonCallback("buttonCallback")

while true do
end

这可以工作。

现在,我不仅想在按下按钮时更新 globalvar,而且还想在 1 分钟间隔内更新它。由于我将不得不访问网络资源,因此我计划使用 socket.select 调用以获取 1 分钟的间隔。

#require "socket"

globalvar = {}

function buttonCallback(buttonId)
    ...访问 globalvar
end

device.RegisterButtonCallback("buttonCallback")

while true do
    socket.select(nil, nil, 60)  -- 等待 60 秒
    ...访问网络
    ...访问 globalvar
end

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

点赞
用户4323
用户4323

假设您使用的库在幕后创建了另一个线程,您仅关心在回调函数中访问 globalvar,您可以通过在回调函数中写入管道并在您的 select 循环中读取它来避免这种情况。换句话说,使用标准的 POSIX 风格管道将回调函数回传到主线程。这是处理例如 POSIX 信号时的常见技术。

2013-02-13 13:53:31
用户734069
用户734069

Lua 在特定的 lua_State 实例中不是线程安全的。当另一个线程正在使用该 Lua 实例时,您 不能 从另一个线程修改全局变量。您绝对不能在同一实例上执行两个不同的脚本。

线程安全是您必须在 Lua 之外处理的事情。您不能让检测按钮按下的 C/C++ 线程直接调用 Lua 代码。它必须通过某种线程安全机制将数据发送到主线程,由 为它们调用 Lua 脚本。

2013-02-13 20:31:32
用户18756
用户18756

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

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

我的最初方法是使用continuations,因为这被奉为代替Lua多线程的方法,但当我阅读Programming in Lua书籍时,它发现为了防止繁忙等待,程序使用socket.select (!)。这增加了我对基于套接字的方法的好感,特别是因为我还需要套接字来访问互联网。

2013-03-11 21:04:58