检查shared_ptr的唯一所有权

时间:2015-01-23 21:18:46

标签: c++11 thread-safety smart-pointers race-condition

我经常希望检查shared_ptr是否是共享对象的唯一所有者。在销毁最后一个shared_ptr之前交换行为会很方便,而不是在销毁之后不得不这样做(我的特定用例是在破坏之前通过用另一个shared_ptr拯救弱指针来处理保存弱指针。已经开始,拯救他们已经太晚了。)

  

C ++ 11 [draft] 20.7.2.1.4:

     

为了确定数据竞争的存在,成员   函数只能访问和修改shared_ptr和weak_ptr   对象本身而不是它们引用的对象。改变在   use_count()不反映可以引入数据的修改   比赛。

This question澄清了我对p.use_count() == 1导致数据竞争的担忧。但是,我仍然不相信以我想要的方式使用它是安全的。

在单线程世界中,如果use_count()返回1,那么您就知道您是该对象的最后一个所有者。在一个你已经避免数据竞争的多线程世界中,use_count()的1足以确保你是唯一的所有者似乎是合理的,但我有一个令人沮丧的时间试图从特别的。我无法判断是否存在允许use_count为1的漏洞,即使另一个线程上存在另一个shared_ptr。另一方面,似乎令人沮丧的是use_count的定义可能会变成goo,因为我将shared_ptr交给了另一个线程。

我是否可以进入use_count()为1的情况,但根据规范的规则,我不是唯一的所有者?我认识到,由于比赛,一个use_count的2并没有明确表示我正在分享(另一个线程可能在我在此线程上调用use_count之后释放我的对象),但我'一旦我看到use_count的1,我就对另一个方向感兴趣。

作为第二个相关问题:同样的规则是否适用于unique,这似乎是根据我想要的实现量身定制的,但是没有关于线程安全的任何额外声明?


修改:为了回答我已经得到的答案,我感兴趣的情况是shared_ptr我们打电话unique_count只能通过单线程,所以我不必担心任何其他线程成功复制它...他们必须找到自己的shared_ptr来复制!

2 个答案:

答案 0 :(得分:3)

如果存在weak_ptr存在与单个shared_ptr相同的控制块,并且另一个线程可能将weak_ptr转换为shared_ptr的可能性然后你的线程可以观察use_count() == 1,但是当它可以对该信息做任何事情时,另一个线程可以从shared_ptr构造一个新的weak_ptr,撞击use_count 1}}最多2个。

即使没有weak_ptr s,如果多个线程对shared_ptr具有读访问权限(例如说它是全局的),那么另一个线程可能会在您观察之后复制它use_count() == 1

如果任何其他线程无法访问您的shared_ptr,并且其他线程不可能将weak_ptr转换为shared_ptr,则use_count() == 1是安全的依靠。

答案 1 :(得分:0)

绝对。即使指定use_count()unique()都是原子的,也不是:

  

long use_count() const noexcept;
  返回: shared_ptr个对象的数量,包括*this,与*this共享所有权,或0   当*this为空时。
   [注意: use_count()不一定有效。 -end note]

     

bool unique() const noexcept;
  返回: use_count() == 1
   [注意: unique()可能比use_count()更快。如果您使用unique()来实现副本   写,不要在get() == nullptr时依赖特定值。 -end note]

没有什么可以阻止这样的事情发生:

std::shared_ptr<Foo> sp;

// thread 1                      // thread 2    
bool uniq = sp.unique();    /**/
                            /**/   std::shared_ptr<Foo> cpy = sp;
if (uniq) {                 /**/
   /* mine?? */             /**/   cpy->foo();
   /* nope :-( */           /**/
}                           /**/