Skip to content

第七章:超时与竞争 ​

本章导读 ​

本章围绕“超时与竞争”展开,先交代适用场景,再说明核心原理,随后给出典型示例,最后补充小结与延伸阅读。

阅读顺序: 结论 → 原理 → 场景 → 代码 → 小结

Q19:BRPOP 超时和 LPUSH 同时发生会怎样?会不会出现"既收到 nil 又拿到元素"的情况? ​

答:

不会。超时检查和 LPUSH 都在主线程的事件循环中串行执行,不可能"同时"发生。

情况 A:LPUSH 先执行

1. LPUSH 执行,发现 W1 在等待链表
2. 把元素发给 W1
3. 移除 W1
4. W1 超时定时器还在,但 W1 已不在等待链表
5. 超时触发时发现 W1 不在链表 → 跳过

结果:W1 拿到元素 ✅

情况 B:超时先执行

1. 超时触发,W1 从等待链表移除
2. 返回 nil 给 W1
3. LPUSH 执行,发现等待链表空(或只有 W2)
4. 元素留在列表中

结果:W1 收到 nil,元素留给下一个 BRPOP ✅

两种情况都不会出现"W1 既收到 nil 又拿到元素"或"元素丢失"。超时处理不会被 LPUSH 打断,LPUSH 也不会被超时处理打断。


Q20:LPUSH + BRPOP 实现 FIFO 队列,那 LPUSH + LPOP 是什么模型?为什么本项目不用 LPUSH + LPOP? ​

答:

推入弹出组合效果
LPUSHBRPOP/RPOP左推右弹FIFO(先进先出队列)
LPUSHLPOP/BLPOP左推左弹LIFO(后进先出栈)
RPUSHBLPOP/LPOP右推左弹FIFO(先进先出队列)
RPUSHBRPOP/RPOP右推右弹LIFO(后进先出栈)

本项目用 LPUSH + BRPOP = FIFO 队列:

LPUSH task:queue 6     ──►    [6]
LPUSH task:queue 7     ──►    [7, 6]
LPUSH task:queue 8     ──►    [8, 7, 6]
                              BRPOP ──►  取出 6(最早推入)
                             [8, 7]
                              BRPOP ──►  取出 7
                             [8]
                              BRPOP ──►  取出 8
                             []

如果用 LPUSH + LPOP(LIFO 栈),后提交的任务会先被消费,先提交的任务可能长时间不被处理,不公平。