深挖 libstdc++ 与 MSVC 源码:智能指针原子操作里那两个被偷走的“低位锁”

发布时间:2026/7/7 10:21:13

深挖 libstdc++ 与 MSVC 源码:智能指针原子操作里那两个被偷走的“低位锁” 引用无锁atomicshared_ptr里最难的那步,不是"原子地把指针从 A 换成 B"。CAS 一个机器字,十年前写无锁栈的时候就反复 cmpxchg 过了。真正的核心是一件听起来像 bug 的事:**读端在 deref 之前,会故意把引用计数先 +1**。读一次,控制块的引用数就瞬时虚高一个。这个多算出来的引用不是浪费,它是整套机制不悬垂、不被 ABA 蒙混的全部依据。把"读"这个动作拆开看:你先 load 到指针,然后必须在碰它指向的对象之前,先在某个计数上占一个坑——占坑成功了,才轮到你 deref。顺序反过来(先 deref 再占坑)就是一个悬垂窗口:另一个线程能在这两步中间把对象 delete 掉,你 deref 的是一块刚被 free 的内存。C20 把atomicshared_ptrT写进了标准(P0718R2)。可你现在链接的 libstdc、MSVC STL、libc,调is_lock_free()没有一个返回true——标准化了一个名字里带"atomic"的类型,三家不约而同地用了锁:libstdc拿控制块指针的最低位当自旋锁,MSVC 用低两位,libc++ 到 2026 年中干脆还没把成员版实现出来,遗留的自由函数走一池互斥锁。真正无锁的那份实现,在 folly 里,靠的正是上面那个"多算一个引用",外加一手把 48 位地址和 16 位计数塞进同一个 8 字节字的打包。

相关新闻