shared_ptr的线程安全开销是多少?

时间:2014-09-11 06:44:53

标签: c++ multithreading shared-ptr

std::shared_ptr保证是线程安全的。我不知道典型实现使用什么机制来确保这一点,但肯定它必须有一些开销。即使您的应用程序是单线程的,也会出现这种开销。

以上情况如何?如果是这样,这是否意味着它违反了原则:如果您没有使用线程安全保证,那么您不会为不使用的内容付费?#34;

2 个答案:

答案 0 :(得分:8)

如果我们查看cppreferencestd::shared_ptr页面,则会在实施说明部分中说明以下内容:

  

为了满足线程安全要求,引用计数器通常使用std::atomic::fetch_add std::memory_order_relaxed递增和递减。

有趣的是要注意实际的实施,例如libstdc++实施文档here说:

  

对于libstdc ++中的shared_ptr版本,编译器和库   是固定的,这使事情变得更简单:我们有一个原子CAS或   我们没有,请参阅下面的锁定政策了解详情。

选择锁定政策部分说明(强调我的):

  

有一个_Sp_counted_base类,它是一个模板   在枚举__gnu_cxx :: _ Lock_policy上参数化。整个家庭   类的参数化在锁定策略中,直到   __shared_ptr,__ weak_ptr和__enable_shared_from_this。实际的std :: shared_ptr类使用锁定策略从__shared_ptr继承   参数根据线程模型自动选择   libstdc ++配置的平台,以便最好的   将使用模板专业化。这种设计是必要的,因为   它不符合shared_ptr的额外模板   参数,即使它有一个默认值。可用的政策是:

     

[...]

     

3._S_Single

     

此策略使用不可重入的add_ref_lock()而不进行锁定。在没有--enable-threads的情况下构建libstdc ++时使用它。

并进一步说(强调我的):

  

对于所有三个策略,引用计数增量和减量为   通过ext / atomicity.h中的函数完成,它检测程序是否正常   是多线程的。 如果只存在一个执行线程   程序然后使用较便宜的非原子操作

所以至少在这个实现中你不会为你不使用的东西买单。

答案 1 :(得分:4)

至少在i386的boost代码中,boost::shared_ptr是使用原子CAS操作实现的。这意味着虽然它有一些开销,但它很低。我希望std::shared_ptr的任何实现都类似。

在高性能数字代码的紧密循环中,我通过切换到原始指针并非常小心地发现了一些加速。但对于普通代码 - 我不担心。