You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

无锁栈pop函数中free()是否安全?orig.head->next访问是否线程安全?

无锁栈pop函数的线程安全问题分析

你的疑问完全正确——这段实现里的next.head = orig.head->next确实存在线程安全隐患,会出现你担心的野指针访问问题,具体分析如下:

问题根源

atomic_load(lfstack)加载的orig只是当前栈顶状态的快照,在do-while循环的重试过程中,orig.head指向的节点可能已经被其他线程成功执行pop并调用free(orig.head)释放了内存。当当前线程恢复执行orig.head->next时,该内存已经不属于栈节点,此时访问next指针属于野指针访问,会触发未定义行为(程序崩溃、数据错乱等)。

核心原因是:在CAS操作成功之前,当前线程并没有获得orig.head节点的所有权,其他线程完全有可能先一步完成该节点的弹出和释放。

为什么标签机制解决不了这个问题

标签(tag)只是解决了ABA问题(即节点被弹出后又重新入栈,导致CAS误判),但它无法保障节点内存的生命周期安全——标签只关联栈顶的状态,不关联节点本身的存活状态。

可行的修复方案

要解决这个问题,必须引入安全的内存回收机制,常见的无锁内存管理方式有两种:

  • 危险指针(Hazard Pointers):线程在访问节点前,先将该节点的指针注册为“危险指针”,表示当前线程正在使用它。只有当确认没有任何线程的危险指针指向该节点时,才真正释放内存。
  • 基于纪元的回收(Epoch-Based Reclamation):将线程的操作划分成不同的纪元,节点被弹出后,延迟到下一个纪元再回收,确保所有可能访问该节点的线程都已经完成当前纪元的操作。

另外,也可以用内存池替代直接free:节点被弹出后不立即释放,而是放回内存池,后续分配新节点时优先复用,避免野指针访问已释放的堆内存。


内容的提问来源于stack exchange,提问作者tongstar

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 17:12:09