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, v in 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
        -- don't `push()` from few threads at the same time
        local lock_push = self.mx_push:lock(val)
        -- don't `pop()` when `push()` and `push()` when `pop()`
        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()的作用
-若原始表在迭代时会被修改,这个循环会至少返回旧状态吗
-在这种情况下,某些kv是否可能不迭代?

另一个问题是我为之编写的应用程序真的是黑盒,我甚至不确定它会在哪个操作系统上运行(Win、Mac、Linux)
我所知道的一切100%都有线程和socket模块。


你能复习一下提供的代码吗
它行得通吗?

互斥还有其他可能吗
也许socket会有所贡献?

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

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, 'deadlock')
        until server
    end,
    unlock = function(self)
        self.server:close()
        self.server = nil
    end
}

最新更新