限量资源(副本入口同一时刻只允许 3 个队伍进入)需要计数闸门:进入前申请一个许可、退出后归还,许可发完则排队等待——这就是信号量。与互斥的区别:互斥只允许 1 个持有者,信号量允许 N 个;实现为一张计数表加申请与归还两个操作。
计数闸门。示例代码如下:
local function newSemaphore(total)
local s = { left = total, wait = {} }
function s.acquire(key)
if s.left > 0 then
s.left = s.left - 1
return true
end
s.wait[#s.wait + 1] = key
return false
end
function s.release()
s.left = s.left + 1
local nxt = table.remove(s.wait, 1)
if nxt then
s.left = s.left - 1
return nxt
end
return nil
end
return s
end
副本入口接线。示例代码如下:
local gate = newSemaphore(3)
local ok = gate.acquire("队伍甲")
print(ok, gate.left)
local nxt = gate.release()
print(nxt)
三个许可发满后第四队进入等待队列——归还时自动唤醒队首。
对比无闸门的反复重试方案:被拒队伍进入等待队列而非空转重试——省掉重试轮询的 CPU(重试版每秒空转约 5000 次判断);信号量本身每次申请一次计数加减,纳秒级。3 许可 10 队争用时,等待队列保证先到先得。
三个不适用场景:一是许可无需归还的场景(一次性门票),计数器即可不需要信号量结构;二是许可数动态变化的资源池,归还要校验池版本;三是 Lua 单线程环境没有真正的并发阻塞——等待队列靠业务 tick 驱动重试,接入方要自己处理重试节奏。
全站技术干货持续更新:996 引擎 / Lua 实战帖,语法、参数与示例一篇讲透。进入文章地图 · 查看全部 →
【语法】 一、隐蔽陷阱 对比两份任务记录的"共同路线":要求连续的子串可以逐位比对,允许跳过中间步骤的最长公共子序列却没法直…
【游戏】 一、业务场景 新玩家出门就挨打,图文教学没人看,第二天流失率居高不下。训练营上线:三个分阶关卡(走位、连招、节奏)…
【语法】 一、隐蔽陷阱 五只猴子分桃,每来一只把桃分成 5 份多 1 个扔掉再拿走一份。正向从 1 个桃开始试,试到几千个才…
【游戏】 一、业务场景 满级玩家装备毕业后一周流失,进度条走到头没了盼头。渡劫玩法上线:80 级可挑战三重天劫,全通获得渡劫…
【语法】 一、隐蔽陷阱 63 分找零用面额 1、5、10、25 的硬币,贪心取最大面额 6 枚搞定;可换成面额 1、3、4 …
【游戏】 一、业务场景 会长每天手动发福利、清名单、盯报名,帮务占满游戏时间,连着三周漏发福利被帮众催。帮会管家上线:每周 …