std::shared_ptr
一样。我的意思是,基本概念很简单,但我真的很困惑如何通过decref加上delete
来避免竞态条件。这个Boost教程演示了如何使用Boost原子库(或C++11原子库)实现原子线程安全的引用计数系统。
#include <boost/intrusive_ptr.hpp>
#include <boost/atomic.hpp>
class X {
public:
typedef boost::intrusive_ptr<X> pointer;
X() : refcount_(0) {}
private:
mutable boost::atomic<int> refcount_;
friend void intrusive_ptr_add_ref(const X * x)
{
x->refcount_.fetch_add(1, boost::memory_order_relaxed);
}
friend void intrusive_ptr_release(const X * x)
{
if (x->refcount_.fetch_sub(1, boost::memory_order_release) == 1) {
boost::atomic_thread_fence(boost::memory_order_acquire);
delete x;
}
}
};
好的,我大致明白了。但是我不明白为什么以下情况是不可能的:
假设 refcount 目前为 1
。
- 线程 A:原子性地将 refcount 减少至
0
。 - 线程 B:原子性地将 refcount 增加至
1
。 - 线程 A:调用指向管理对象的指针的
delete
方法。 - 线程 B:视 refcount 为
1
,访问管理对象指针... 段错误!
我无法理解是什么阻止了这种情况的发生,因为并没有防止数据竞争在 refcount 变为 0 和对象被删除之间发生。decref
refcount 和调用 delete
是两个独立的、非原子的操作。所以,如果没有锁,这怎么可能?