【问题标题】:Partial template specialization of std::atomic for smart pointers用于智能指针的 std::atomic 的部分模板特化
【发布时间】:2020-12-15 22:11:48
【问题描述】:
背景
从 C++11 开始,对 std::shared_ptr 的原子操作可以通过找到 here 的 std::atomic_... 方法完成,因为如下所示的部分特化是不可能的:
std::atomic<std::shared_ptr<T>>
这是因为std::atomic 只接受TriviallyCopyable 类型,而std::shared_ptr(或std::weak_ptr)不可轻易复制。
但是,从 C++20 开始,这些方法已被弃用,并被 std::atomic 的部分模板特化替换为 std::shared_ptr,如 here 所述。
问题
我不确定
- 为什么
std::atomic_... 被替换了。
- 用于为智能指针启用
std::atomic 的部分模板特化的技术。
【问题讨论】:
标签:
c++
c++11
atomic
smart-pointers
c++20
【解决方案1】:
atomic<shared_ptr> 或类似性质的一些建议解释了各种原因。特别值得注意的是P0718,它告诉我们:
C++ 标准提供了一个 API 来以原子方式访问和操作特定的 shared_ptr 对象,即,当从多个线程操作同一对象而无需进一步同步时,不会引入数据竞争。此 API 脆弱且容易出错,因为通过此 API 操作的 shared_ptr 对象与其他 shared_ptr 对象无法区分,但受限于只能通过此 API 操作/访问它们。特别是,如果不先将此类 shared_ptr 加载到另一个 shared_ptr 对象中,然后通过第二个对象取消引用,则无法取消引用。
N4058 解释了关于如何实现这样的事情的性能问题。由于shared_ptr 在大小上通常大于单个指针,因此原子访问通常必须使用自旋锁来实现。所以要么每个shared_ptr 实例都有一个自旋锁,即使它从未被原子地使用,或者这些原子函数的实现必须有一个用于单个对象的自旋锁的后备表。或者使用全局自旋锁。
如果您有一个专门用于原子的类型,这些都不是问题。
atomic<shared_ptr> 实现可以在 T 太大而无法适应 CPU 原子操作时使用 atomic<T> 的常用技术。他们可以通过法令绕过 TriviallyCopyable 限制:标准要求它们存在并且是原子的,因此实现使其如此。 C++ 实现不必遵循与常规 C++ 程序相同的规则。