I'm trying to understand exactly how thread-safe, atomic reference counting works, for example as with std::shared_ptr.  I mean, the basic concept is simple, but I'm really confused about how the decref plus delete avoids race conditions.
This tutorial from Boost demonstrates how an atomic thread-safe reference counting system can be implemented using the Boost atomic library (or the C++11 atomic library).
#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;
    }
  }
};
Okay, so I get the general idea. But I don't understand why the following scenario is NOT possible:
Say the refcount is currently 1.
- Thread A: atomically decrefs the refcount to 0.
- Thread B: atomically increfs the refcount to 1.
- Thread A: calls deleteon the managed object pointer.
- Thread B: sees the refcount as 1, accesses the managed object pointer... SEGFAULT!
I can't understand what prevents this scenario from occurring, since there is nothing preventing a data race from between the time the refcount reaches 0, and the object is deleted.  Decrefing the refcount and calling delete are two separate, non-atomic operations.  So how is this possible without a lock?
 
     
     
     
     
    