问题描述
背景
自C ++ 11起,可以通过here的std::shared_ptr
方法对std::atomic_...
进行原子操作,因为不可能进行如下所示的部分专业化:
std::atomic<std::shared_ptr<T>>
这是由于std::atomic
仅接受TriviallyCopyable类型,而std::shared_ptr
(或std::weak_ptr
)不可复制。
但是,自C ++ 20起,已弃用这些方法,并已由here中所述的std::atomic
的{{1}}的部分模板专用化代替。
问题
我不确定
- 为什么
std::shared_ptr
被替换了。 - 用于为智能指针启用
std::atomic_...
的部分模板专业化的技术。
解决方法
针对atomic<shared_ptr>
或类似性质的一些建议解释了多种原因。特别值得注意的是P0718,它告诉我们:
C ++标准提供了一个API,可以原子地访问和操作特定的
shared_ptr
对象,即,当从多个线程中操作同一对象而不进行进一步同步时,不会引入数据争用。该API易碎且容易出错,因为通过此API操作的shared_ptr
对象与其他shared_ptr
对象是无法区分的,但受到只能通过此API操作/访问它们的限制。特别是,您必须先将这样的shared_ptr
加载到另一个shared_ptr
对象中,然后再通过第二个对象进行引用,才能取消引用。{p>
N4058解释了有关如何实现此类问题的性能问题。由于shared_ptr
的大小通常大于单个指针,因此原子访问通常必须使用自旋锁来实现。因此,即使每个shared_ptr
实例都即使没有被原子使用也没有一个自旋锁,或者这些原子功能的实现必须为各个对象提供一个自旋锁的后备表。或使用全局自旋锁。
如果您有一个专用于原子的类型,那么这些都不是问题。
当atomic<shared_ptr>
太大而无法容纳CPU原子操作时, atomic<T>
实现可以对T
使用常规技术。它们可以通过命令来绕过TriviallyCopyable限制:该标准要求它们必须存在并且必须是原子的,因此实现必须做到这一点。 C ++实现不必遵循与常规C ++程序相同的规则。