Apollo 技术文档Apollo 技术文档
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
指南
  • 架构概述
  • BigWorld 架构深度解析
  • BigWorld 进程架构与玩家生命周期
  • AOI九宫格系统详解
  • AOI广播与消息去重
  • Base 模块
  • Core 模块
  • Runtime 模块
  • Data 模块
  • Network 模块
  • /modules/actor.html
  • Game 模块
  • BigWorld 模块
服务器应用
API 参考
QA
GitHub
  • MMORPG 架构 QA

Q74: 如何设计无锁数据结构?

核心结论

无锁数据结构不是“更高级的线程安全容器”,而是一种在特定热点场景下,用原子操作替代互斥锁的高成本手段。

它适合:

  • 并发模型明确
  • 争用热点清楚
  • 性能收益足够大

如果这些前提不成立,无锁结构往往只会把代码复杂度和调试成本抬得很高。

一、无锁到底在解决什么问题

它主要想减少的是:

  • 锁等待
  • 上下文切换
  • 热点临界区串行化

所以无锁结构最值得用在“锁已经被证明是热点瓶颈”的地方,而不是为了追求概念先进。

二、无锁不等于无代价

常见代价包括:

  • 内存序理解复杂
  • ABA 问题
  • 生命周期管理困难
  • 调试和验证成本高

也就是说,它只是把问题从 mutex 转移到了原子和内存模型层。

三、并发模型越简单,无锁越有机会成功

例如:

  • SPSC 队列
  • MPSC 队列

这类模型通常比通用 MPMC 结构更容易做得稳定。

并发模型越复杂,无锁实现的维护成本就越高。

四、生命周期管理是无锁结构最难的部分之一

即使原子更新逻辑写对了,节点什么时候能安全释放仍然是大问题。

这就是为什么无锁结构经常需要配套:

  • hazard pointers
  • epoch-based reclamation
  • 引用计数或延迟回收

很多难点根本不在 CAS 本身。

五、无锁结构更适合小而明确的热点

例如:

  • 热门队列
  • 统计计数器
  • 某些固定模型的 ring buffer

如果要做一个功能全面、泛型很强、可任意扩展的“无锁万能容器”,通常很容易失控。

六、工程上更稳妥的顺序

更务实的做法通常是:

  1. 先确认锁真的是瓶颈
  2. 先尝试分片、降共享、缩短临界区
  3. 只有在收益明确时,再上无锁结构

这比一上来全盘 lock-free 更稳。

七、常见误区

1. 无锁一定比加锁快

不一定。低争用场景下,简单锁结构可能更稳、更快。

2. 用 CAS 就算无锁设计

远远不够。内存序、ABA 和回收才是真正难点。

3. 所有线程安全容器都该追求无锁

这通常会带来过高复杂度,不符合多数业务场景。

参考资料

  • CAS、内存序和无锁回收机制相关资料
在 GitHub 上编辑此页
最后更新: 3/20/26, 6:06 AM
贡献者: cuihairu