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
对象本身不是原子的(即使是,在另一个线程中访问它之前潜在地销毁它也会导致未定义的行为)。它只是线程安全的,因为可以跨线程自由地创建和销毁额外的拥有副本,而不会导致数据竞争、对拥有对象的引用计数变得不一致或对象被多次销毁。
这是 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
对象本身不是原子的(即使是,在另一个线程中访问它之前潜在地销毁它也会导致未定义的行为)。它只是线程安全的,因为可以跨线程自由地创建和销毁额外的拥有副本,而不会导致数据竞争、对拥有对象的引用计数变得不一致或对象被多次销毁。