直接用 sync.Mutex 不算“无锁”,因其依赖操作系统互斥原语,会阻塞、调度和上下文切换,不满足 Lock-Free 的进度保证;真正的无锁需基于 CAS 等原子指令实现。

为什么直接用 sync.Mutex 不算“无锁”?
无锁(Lock-Free)不是“不用锁”,而是不依赖操作系统级互斥原语,靠 CPU 提供的原子指令(如 CAS)保证多线程安全。一旦用了 sync.Mutex 或 sync.RWMutex,哪怕只锁几行,就已退出 Lock-Free 范畴——它会阻塞、调度、产生上下文切换开销,还可能被抢占。
- 真正的 Lock-Free 队列必须满足:至少一个线程总能在有限步内完成操作(progress guarantee),哪怕其他线程停住或崩溃
- Go 标准库没有内置 Lock-Free 队列,
container/list和chan都不是;chan底层用的是 mutex + condition variable - 别被 “atomic” 包名骗了:
atomic.CompareAndSwapUintptr是 CAS 基石,但光有它不等于队列无锁——结构设计、ABA 问题、内存序、垃圾回收协同才是难点
atomic.CompareAndSwapPointer 怎么用才不崩?
Go 的 atomic.CompareAndSwapPointer 是实现无锁队列的核心,但它只做“比较并交换指针”,其余全得自己扛:
- 必须传入 指针的地址(
&node.next),不是 node.next 本身 - 第三个参数是“期望旧值”,必须和当前内存中值 完全相等(包括 nil vs 未初始化零值)
- 如果 node 是栈上分配的局部变量,取其地址传给
atomic函数会导致 panic —— 所有参与 CAS 的节点必须堆上分配(new(Node)或&Node{}) - 常见错误:用
unsafe.Pointer(&x)强转普通变量地址,运行时可能 crash 或静默失败
// 正确:节点在堆上,next 字段可被原子更新
type Node struct {
value int
next unsafe.Pointer // 指向下一个 Node
}
// CAS 更新 next:
old := atomic.LoadPointer(&head.next)
for !atomic.CompareAndSwapPointer(&head.next, old, newNext) {
old = atomic.LoadPointer(&head.next)
}
ABA 问题在 Go 里真能忽略吗?
能忽略,但仅限于指针场景且 GC 正常工作时。Go 的垃圾回收器(尤其是三色标记 + 写屏障)保证:只要一个对象还在被任何 goroutine 可达,就不会被回收。这意味着:
- 如果你用
unsafe.Pointer存的是 *Node,且没漏掉引用(比如没把指针存进 map 后又删掉),那么 ABA 不会发生:同一地址不可能被重复分配给新 Node - 但若手动管理内存(比如用
sync.Pool复用 Node 并清空字段),就可能触发 ABA:旧 Node 被放回池 → 新 Node 分配到同一地址 → CAS 误判为“没变过” - 解决方案不是加版本号(像 C++ 的
std::atomic<std::shared_ptr>),而是避免复用指针值:每次new(Node),或用sync.Pool时确保字段彻底重置(包括 next = nil)
生产环境敢用自研 Lock-Free 队列吗?
不敢,除非你已满足以下全部条件:
立即学习“go语言免费学习笔记(深入)”;
- 已跑通 TSAN(Go 的
-race)和大量 goroutine 压测(100+ goroutines 持续 push/pop 数百万次) - 已验证 GC 峰值延迟不因节点频繁分配/释放而抖动(用
runtime.ReadMemStats对比 baseline) - 已确认目标 Go 版本对
unsafe.Pointer/atomic行为无变更(Go 1.19+ 对unsafe使用更严格) - 已对比过成熟第三方实现(如
github.com/Workiva/go-datastructures/queue的ConcurrentQueue)——它用的是细粒度 mutex,实测吞吐反而更高、更稳
真正需要 Lock-Free 的场景极少:高频 tick(>100k/s)、硬实时子系统、或嵌入式资源受限环境。多数 Web/微服务场景,一个带缓冲的 chan 或封装好的 sync.Pool + mutex 队列更省心、更易 debug。
别为了“无锁”写一堆 atomic 调用,最后发现 goroutine 调度开销远大于锁争用——那是拿锤子找所有螺丝钉。










