shared_ptr线程安全的开销是多少?
What's the overhead from shared_ptr being thread-safe?
std::shared_ptr
保证是线程安全的。我不知道典型的实现使用什么机制来确保这一点,但肯定会有一些开销。即使在应用程序是单线程的情况下,这种开销也会存在。
是上述情况吗?如果是这样的话,如果你没有使用线程安全保证,这是否意味着它违反了"你不为你不使用的东西付费"的原则?
如果我们查看std::shared_ptr的cppreference页面,它们会在实现说明部分中声明以下内容:
为了满足线程安全要求,引用计数器通常使用std::atomic::fetch_add和std::memory_order_relaxed进行递增和递减。
注意一个实际的实现是很有趣的,例如这里的libstdc++实现文档说:
对于libstdc++中shared_ptr的版本,编译器和库是固定的,这使事情变得更简单:我们有一个原子CAS或我们没有,请参阅下面的锁定策略以了解详细信息。
选择锁定策略部分显示(强调矿):
有一个_Sp_counted_base类,它是一个模板在枚举__gn_cxx::_Lock_policy上参数化。整个家庭的类在锁策略上参数化,直到__shared_ptr、__weak_ptr和__enable_shared_from_this。实际的std::shared_ptr类通过锁定策略从__shared_ptr继承基于线程模型自动选择的参数,以及为其配置libstdc++的平台,以便获得最佳可用将使用模板专用化。这种设计是必要的,因为sharedptr有一个额外的模板是不符合要求的参数,即使它有默认值。可用的策略有:
[…]
3._S_单
此策略使用不带锁定的不可重入add_ref_lock()。当在没有--enable线程的情况下构建libstdc++时,将使用它。
并进一步表示(强调矿):
对于所有三个策略,引用计数的增量和减量分别为通过ext/atomicity.h中的函数完成,这些函数检测程序是否是多线程的如果则使用成本较低的非原子操作。
所以,至少在这个实现中,你不会为你不使用的东西付费。
至少在i386上的boost代码中,boost::shared_ptr
是使用原子CAS操作实现的。这意味着,虽然它有一些开销,但它相当低。我希望std::shared_ptr
的任何实现都是类似的。
在高性能数字代码的紧密循环中,我发现切换到原始指针并非常小心会加快速度。但对于普通代码,我不会担心。
- 实现无开销push_back的最佳方法是什么
- 复制列表初始化的隐式转换的等级是多少
- while循环中while循环的时间复杂度是多少
- 如何检查一个c++字符串中有多少相同的字符/数字
- C++有多少类型的循环
- 求出有多少个数字是完美平方,而sqrt()是L,R范围内的素数
- 在条件变量中触发错误信号的频率是多少
- 定义类型的成本/开销是多少?
- 此操作在C++中通过引用进行修改的开销是多少
- 如果类没有任何成员变量,则通过临时对象调用类的成员函数的开销是多少?
- 每个对象内存分配有多少开销
- 与C 中的普通指针相比,智能指针的开销是多少
- 如果内部的总工作量相同,那么将for循环拆分为多个for循环的开销是多少
- 如果一类继承nsobject,则放置多少开销
- C++:contst static DEBUG 和 if 语句,实际的执行时间开销是多少
- shared_ptr线程安全的开销是多少?
- C++智能指针取消引用 - 检查它是否已初始化的开销是多少?
- 包装器函数的开销应该是多少?
- getaddrinfo()的时间开销是多少?
- 如果在保持相同类型的同时添加constness, static_cast运行时开销是多少?