【问题标题】:Does C++ offer a thread-safe reference counter?C++ 是否提供线程安全的引用计数器?
【发布时间】:2021-10-26 08:46:27
【问题描述】:

标准 C++ 库中是否有线程安全的引用计数器类(或作为 Visual Studio 中的扩展),还是我需要从头开始编写这种对象?

我希望有一个像shared_ptr 那样纯粹执行引用计数的对象,但它可以跨多个线程准确地执行此操作,并且无需管理任何东西。 shared_ptr 它的表亲结构很好,因为它们定义了您需要的所有复制构造函数和赋值运算符,这对我来说是 C++ 中最容易出错的部分; C++ 构造函数之于 C++ 就像开球之于美式足球一样。

struct Fun {

    // this member behaves in a way I appreciate, save for 2 short-comings:
    // - needless allocation event (minor)
    // - ref counting is only estimate if shared across threads (major)
    std::shared_ptr<int> smartPtr {new int};  

    // this is the hypothetical object that I'm searching for
    // + allocates only a control block for the ref count
    // + refCount.unique() respects reality when refs exist across many threads
    //   I can always count on this being the last reference
    std::object_of_desire refCount;

    // no explicit copy constructors or assignment operators necessary
    // + both members of this class provide this paperwork for me, 
    //   so I can careless toss this Fun object around and it'll move
    //   as one would expect, making only shallow copies/moves and ref counting
    Fun(); 

    ~Fun(){
        if(refCount.unique()){
             smart_assert("I swear refCount truly is unique, on pain of death");
        }
    }
}

【问题讨论】:

  • 我不明白你的问题。为什么你不想使用 shared_ptr?
  • 这能回答你的问题吗? std::shared_ptr thread safety explained
  • 如果您不能将refCount.unique() 锁定为线程安全值,那么它的目的是什么?在您调用 unique 和调用 smart_assert 之间可能会增加
  • shared_ptr 进行线程安全引用计数,如果您将其设置为不管理任何内容,它就无法管理任何内容。所以没有必要重新发明轮子。
  • @AnneQuinn 在您调用unique 之后,是什么阻止了另一个线程复制最后一个引用?

标签: c++ reference-counting


【解决方案1】:

关于线程安全的警告 w.r.t. std::shared_ptr

  • 如果您有多个线程可以访问同一个指针 对象,那么如果其中一个线程修改了指针,则可能会发生数据竞争。如果每个线程都有自己的实例,指向相同的共享状态,则共享状态上没有数据竞争。
  • 线程上指向对象的最终修改不会inter-thread happens before另一个线程观察use_count为1。如果没有修改指向对象,则指向对象上没有数据竞争对象。

这是你想要的类型

class ref_count {
public:
    bool unique() const { return ptr.use_count() == 1; }
private:
    struct empty {};
    std::shared_ptr<empty> ptr = std::make_shared<empty>();
};

【讨论】:

  • use_count 不一定准确
  • @M.M 访问共享状态有一个总顺序,我们不公开指针或共享对象,因此警告不适用
  • 鉴于 cppref 中提到的警告,我同意这是安全的。 IMO,将有助于在答案中简要说明它们。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 1970-01-01
  • 2011-03-08
相关资源
最近更新 更多