Lua简单互斥锁,适用于多线程应用程序。

我正在为某个应用程序编写扩展/插件。

文档中说明插件有两个线程:

  • “主线程”必须驻留所有业务逻辑

  • “回调线程”在应用程序通过事件调用预定义名称的回调时,这些回调不能执行复杂的操作并尽快返回

文档不是很清楚,因此可以从多个线程调用回调函数。

我编写了虚拟互斥体,如下所示:

Mutex = class{
    _lock = function(self, owner)
        assert(owner, 'owner must be set')
        local ts = Timestamp.get()
        local key = tostring(owner) .. ' ' .. tostring(ts)
        self[key] = ts
        for k, vin pairs(self) do
            if k ~= key and v <= ts then
                self[key] = nil
                return false
            end
        end
        return key
    end,
    lock = function(self, owner, wait)
        local wait = wait or 0.01
        local k
        repeat
            k = self:_lock(owner)
            if k then return k else sleep(wait) end
        until k
    end,
    unlock = function(self, key)
        self[key] = nil
    end
}

并将其用于创建线程安全队列,如下所示:

ThreadSafeQueue = class{
    new = function(cls)
        return getmetatable(cls).new(cls, {
            mx_queue = Mutex:new(),
            mx_push = Mutex:new(),
        })
    end,
    pop = function(self)
        local lock_queue = self.mx_queue:lock(self)
        local val
        if #self then
            val = table.remove(self, 1)
        else
            val = nil
        end
        self.mx_queue:unlock(lock_queue)
        return val
    end,
    push = function(self, val)
        if val == nil then return end
        -- 不要同时从多个线程进行“push()”
        local lock_push = self.mx_push:lock(val)
        -- 不要在“push()”时“pop()”,在“pop()”时“push()”
        local lock_queue = self.mx_queue:lock(self)
        self[#self + 1] = val
        self.mx_queue:unlock(lock_queue)
        self.mx_push:unlock(lock_push)
    end
}

这里的“class”是一个帮助函数,返回带有原型查找和“:new()”方法的对象,并设置元表。

主要问题是我不确定“pairs()”的作用。

  • 如果在迭代时修改原始表,这个循环会返回至少旧状态吗?

  • 在这种情况下,有可能某些“k”、“v”没有被迭代吗?

另一个问题是我编写的应用程序实际上是黑匣子,我甚至不确定它将在哪个操作系统上运行(Win、Mac、Linux)。

我能确定的是我有线程和“socket”模块。


您能够审查提供的代码吗?

它能工作吗?

有没有其他互斥体的可能性。

或者“socket”能提供什么?

点赞
用户1243636
用户1243636

选项:用于套接字

尝试创建套接字,如果成功,则互斥锁定,否则-等待它关闭

local Mutex = class {
    identities = {},
    new = function(cls, identity)
        assert(not cls.identities[identity])
        local inst = getmetatable(cls).new(cls, {
            port = identity,
            server = nil
        })
        cls.identities[identity] = inst
        return inst
    end,
    lock = function(self, wait)
        local wait = wait or 0.01
        local server
        local ts = Timestamp.get()
        repeat
            server = socket.bind("*", self.port)
            if server then
                self.server = server
                return true
            else
                sleep(wait)
            end
            assert(Timestamp.get() - ts < 3, '死循环')
        until server
    end,
    unlock = function(self)
        self.server:close()
        self.server = nil
    end
}
2015-03-06 13:10:02