【发布时间】:2016-08-03 16:52:44
【问题描述】:
Poco RefCountedObject 提供 2 个接口:
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 开始执行释放并到达 --_counter
- 开始执行重复并到达 ++_counter
- 此时_counter=1
- B 执行 --_counter 并返回要由 if 评估的结果(即 0 && counter 现在为 0)
- B 在分支语句(if)之前被抢占并停止
- 执行 _counter++ 并返回对对象的引用
- B 继续并评估值为 0 的分支语句并删除对象
我们最终得到 A 引用了一个已删除的对象。 即使 mutable 关键字强制编译器不优化 _counter 它也无助于多线程
我错过了什么吗?
【问题讨论】:
标签: c++ multithreading poco poco-libraries