shared_ptr refcounter 实施 thead 安全

shared_ptr refcounter implementation thead safety

这是 VisualStudio 2017

shared_ptr 的实现

MSDN 声明引用计数块是线程安全的。 我想知道,如果在 thread1 中我们检查 rep 是否为 null (if (_Other._Rep) //1),
怎么办 然后 thread2 检查 rep 是否为 null,将 refcounter 减少到 0 并调用 _Destroy(); 之后线程 1 尝试增加已删除的引用计数器。是不是有问题还是我哪里理解错了?

void _Copy_construct_from(const shared_ptr<_Ty2>& _Other)
{   // implement shared_ptr's (converting) copy ctor
    if (_Other._Rep) //1
    {
        _Other._Rep->_Incref();
    }

    _Ptr = _Other._Ptr;
    _Rep = _Other._Rep;
}

void _Decref()
  { // decrement reference count
    if (_Rep) //2
    {
        _Rep->_Decref(); //3
    }
  }

void _Decref()
{   // decrement use count
    if (_MT_DECR(_Uses) == 0)
    {   // destroy managed resource, decrement weak reference count
        _Destroy();
        _Decwref();
    }
}

更新:

 thread1: ctor (_Copy_construct_from)
  thread1: if (_Other._Rep) 
  thread2 _Decref
  thread2 _Rep->_Decref();
  thread2 _Destroy();
  thread1 _Other._Rep->_Incref(); // but object is already destroed 

您在第一块中显示的代码是复制或转换构造函数的一部分,例如您正在调用以下内容:

std::shared_ptr<A> some_shared_ptr = some_other_shared_ptr;

当线程执行该行时,some_other_shared_ptr 当前不拥有任何对象或者它正在拥有一个对象。如果它拥有一个对象,那么它将在该语句的执行期间继续拥有该对象。因此拥有对象的引用计数至少为1,不能变为0,并且该对象不会在语句执行时被销毁。

如果另一个线程在另一个线程执行该语句时潜在地破坏或修改(例如通过重置它)some_other_shared_ptr 对象本身,则该程序具有数据竞争和未定义的行为。 shared_ptr 对象本身不是原子的(即使是,在另一个线程中访问它之前潜在地销毁它也会导致未定义的行为)。它只是线程安全的,因为可以跨线程自由地创建和销毁额外的拥有副本,而不会导致数据竞争、对拥有对象的引用计数变得不一致或对象被多次销毁。