c++ - Poco RefCountedObject 线程安全吗?

标签 c++ multithreading poco poco-libraries

Poco RefCountedObject 提供 2 个接口(interface):

    inline void RefCountedObject::duplicate() const
{
    ++_counter;
}


inline void RefCountedObject::release() const throw()
{
    try
    {
        if (--_counter == 0) delete this;
    }
    catch (...)
    {
        poco_unexpected();
    }
}

与:

class Foundation_API RefCountedObject
    /// A base class for objects that employ
    /// reference counting based garbage collection.
    ///
    /// Reference-counted objects inhibit construction
    /// by copying and assignment.
{
public:
    RefCountedObject();
        /// Creates the RefCountedObject.
        /// The initial reference count is one.

    void duplicate() const;
        /// Increments the object's reference count.

    void release() const throw();
        /// Decrements the object's reference count
        /// and deletes the object if the count
        /// reaches zero.

    int referenceCount() const;
        /// Returns the reference count.

protected:
    virtual ~RefCountedObject();
        /// Destroys the RefCountedObject.

private:
    RefCountedObject(const RefCountedObject&);
    RefCountedObject& operator = (const RefCountedObject&);

    mutable AtomicCounter _counter;
};

请注意: 可变的 AtomicCounter _counter;

我的问题是如果我在多线程中使用 RefCountedObject 是否安全?

在我看来,这并不是因为只有 --_counter 是原子的,而 if(--_count) 不是原子的,并且可能导致引用已删除的对象。 例如假设我有 2 个线程 A 和 B,一个执行复制,另一个执行释放,执行顺序如下:

  • B开始执行release并到达--_counter
  • A开始执行duplicate并到达++_counter
  • 此时_counter=1
  • B 执行 --_counter 并返回 if 评估的结果(即 0 && counter 现在为 0)
  • B 被抢占并在分支语句(if)之前停止
  • A 执行 _counter++ 并返回对象的引用
  • B 继续计算值为 0 的分支语句并删除对象

我们最终得到 A 引用了一个已删除的对象。 即使 mutable 关键字强制编译器不优化 _counter,它也无助于多线程

我错过了什么吗?

最佳答案

严格孤立地看重复和发布,以上是正确的。

但是,如果您有两个线程,它们都有一个指向同一个 RefCountedObject 的指针,那么您应该在每个线程中有单独的 AutoPtr 实例(这意味着开始时 _counter > 1),或者,如果您共享相同的AutoPtr,如果至少有一个线程可以更改 AutoPtr(这将导致调用 release()),则它必须由互斥体保护。不用说,在多个线程之间共享一个可变的 AutoPtr 是灾难的根源。

如果您通过手动调用 duplicate() 和 release() 来管理 RefCountedObject(我不推荐这样做),您应该遵循 POCO 的引用计数规则并非常小心。

因此,对于行为良好的代码,RefCountedObject 和 AutoPtr 对于多线程使用是安全的。

关于c++ - Poco RefCountedObject 线程安全吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38749500/

相关文章:

entity-framework - Entity Framework 兼容 POCO 的最短语法

WCF REST 服务不会返回实体的 child

c++ - 将图标从数组添加到 QListWidget 项目

c++ - 模棱两可的赋值运算符

c++ - 替换所有对 printf 的调用的宏

java - 我应该创建一个新线程作为扩展 Thread 的类,还是只进行一个新的 Thread 对象实例化?

c++ - Visual Studio 2013 - C++ 错误

c++ - 从 C++ 中的基方法调用重写的子方法

c++ - 线程池如何让我处理许多客户端连接?

ios - 可以跨线程安全地访问 bool var 吗?