地址没变但里面的东西已经换了一茬CAS 被骗了。打个比方你桌上放了杯奶茶你瞅了一眼是珍珠奶茶你转身去接个电话。这 5 分钟里同事把奶茶喝完了杯子扔了保洁阿姨把杯子捡回来又倒了杯新的珍珠奶茶进去杯子还是那个杯子位置也没变你回来一看哟奶茶还在于是你放心地拿起来喝了一口。但这是另一杯奶茶了。对应到代码里CAS 就是那个瞅一眼的操作// 你瞅了一眼head 指向地址 A old head.load(); // 你去干别的事了被别的线程抢占了 // 这时候 // 别的线程把 A 弹走了 // 释放了 A 的内存 // 又分配了新节点刚好分配到同一个地址 A // 你回来CAS 检查head 还是 A 吗 // 是地址一样CAS 成功 head.compare_exchange_strong(old, new_ptr);CAS 只认地址不认这个地址里装的是不是原来的东西。为什么叫 ABA因为变化路径是A → B → A你开头看到 A结尾看到 A中间 B 发生过啥CAS 根本不知道。就像你早上看女朋友在沙发上晚上看还在沙发上中间她换了个灵魂你不知道。为什么这么坑因为 CAS 成功后你拿着旧记忆去操作你以为A-next还是原来的 B其实 A 里面的数据已经全换了你基于错误的前提改结构链表断、内存重复释放、读到别人的数据而且这种 bug 特别阴间单线程跑永远不出低并发跑几个月不出高并发压测随机崩还不一定能复现怎么治1. 加版本号——给每个地址办个身份证A:第1代 → B:第2代 → A:第3代你手上是 A 第 1 代现在系统是 A 第 3 代CAS 一眼识破。2. 不让内存复用——别人还在用 A 的时候谁都不许 delete A等确认没人用了再真正释放。地址永远不会死而复生。3. 用句柄不用裸指针——发身份证不发人脸槽位3第5代槽位 3 后来被复用但代次变成 6你拿第 5 代的票来用系统直接拒。一句话总结CAS 是认脸的ABA 就是脸没变魂换了。版本号让它能认魂Hazard Pointer 不让魂投胎句柄直接不发人脸发身份证。