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

《C++ Concurrency in Action》拆分引用计数示例技术疑问

《C++ Concurrency in Action》第二版无锁栈实现问题解答

代码片段

template<typename T>
class lock_free_stack
{
private:
    struct node;
    struct counted_node_ptr
    {
        int external_count;
        node* ptr;
    };
    struct node
    {
        std::shared_ptr<T> data;
        std::atomic<int> internal_count;
        counted_node_ptr next;
        node(T const& data_):
            data(std::make_shared<T>(data_)),
            internal_count(0)
        {}
    };
    std::atomic<counted_node_ptr> head;
public:
    ~lock_free_stack()
    {
        while(pop());
    }
    void push(T const& data)
    {
        counted_node_ptr new_node;
        new_node.ptr=new node(data);
        new_node.external_count=1;
        new_node.ptr->next=head.load();
        while(!head.compare_exchange_weak(new_node.ptr->next,new_node));
    }
};

Q1:push方法中,新创建的counted_node_ptr分配在栈上,push()返回后head是否会成为悬空指针?是否存在理解遗漏?

不会。这里的核心是区分counted_node_ptr本身的存储和它内部ptr指向的对象:

  • 栈上的new_node是临时的counted_node_ptr实例,它的ptr指向堆上动态分配的node对象;
  • head是原子类型的counted_node_ptr变量,调用compare_exchange_weak时,会把new_node的内容(包括external_count和ptr的值)完整复制到head中;
  • 当push返回后,栈上的new_node被销毁,但head中存储的是独立的副本,其ptr依然指向堆上的node,因此head不会成为悬空指针。

常见的理解遗漏是混淆了“计数结构的存储位置”和“链表节点的存储位置”——临时变量只是传递节点信息的载体,真正的链表节点在堆上,head保存的是节点的引用信息副本,和临时变量无关。


Q2:书中双引用计数机制中,external_count与internal_count之和为节点总引用数。为何单计数器不足以实现?两者分别代表什么?

单计数器的局限性

在无锁并发场景下,单引用计数无法区分两种关键的引用类型:

  • 一种是链表结构中持久存在的引用(比如head或其他节点的next指向该节点);
  • 另一种是线程操作过程中持有的临时引用(比如线程加载了节点指针,正在进行修改或读取操作)。

如果只用单计数器,当线程尝试删除节点时,可能出现其他线程还持有临时引用的情况,导致内存提前释放;或者无法准确判断节点是否真正无人使用,造成内存泄漏。

双计数器的含义

  • external_count:代表链表结构中指向该节点的外部引用数量。每个counted_node_ptr实例中的external_count就是对该节点的一次外部引用——比如head指向节点时,对应external_count为1,后续如果有新节点插入到它前面,新节点的next也会持有该节点的一次外部引用。
  • internal_count:代表线程正在持有该节点的临时引用数量。当线程需要操作某个节点时,会先复制节点的指针,此时internal_count递增,用来跟踪这些未完成的操作;当操作完成后,internal_count递减。

只有当external_count + internal_count的总和为0时,才说明该节点既没有被链表结构引用,也没有线程在操作它,可以安全销毁。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.30 17:16:29