我在堆上分配了一些很少修改但需要快速读取访问权限的数据结构。一个例子是在堆上分配的结构,许多线程以只读方式非常频繁地访问该结构。这个结构需要定期重写并避免锁定争用我想知道使用auto_ptr
是否可以安全地使用获取引用的线程继续处理直到它们完成但允许编写器生成结构的副本,重写它并快速交换指针与结构的新auto_ptr
实例。
我从Java中的CopyOnWriteArrayList
得到了这个想法,并希望在C ++中执行类似的性能。
答案 0 :(得分:8)
std::auto_ptr
在调用{const reset()
之类的非const成员时没有任何线程安全保证。此外,您应该考虑将std::unique_ptr
作为auto_ptr
替换为auto_ptr
的{{1}}实际上已被弃用。
std::shared_ptr
提供此类线程安全保证。
shared_ptr
通常保证的是,引用计数是以原子方式操作的,这意味着在创建shared_ptr
的副本时,您可以安全地避免数据争用,前提是没有人目前正在修改shared_ptr
。
考虑shared_ptr
的以下用例。您有一个全局shared_ptr<string> sharedString;
,当前指向std::string
的实例。许多线程可以安全地调用get()
来检索指向字符串的指针。他们也可以创建自己的共享指针,如下所示:shared_ptr<string> myString = sharedString;
,前提是没有人正在改变共享指针所指向的内容。
现在,让我们回过头来修复示例中存在的竞争条件。当需要更改全局共享指针指向的内容时,线程可能正在复制它 - 这是一个问题,因为它可能使副本处于不一致状态。因此,我们必须确保以原子方式更改和复制它。
幸运的是,shared_ptr
提供了许多C ++ 11原子操作的特殊化:atomic_load
,atomic_store
和atomic_exchange
。
制作shared_ptr
的副本时,请使用atomic_load
,并在更新shared_ptr
时使用atomic_store
。
这样做很重要,原因有两个。
现在,重要的是要注意在shared_ptr
上使用线程安全操作不会为它指向的类型提供任何线程安全性。您始终必须注意所指向的对象是以线程安全的方式使用。
答案 1 :(得分:2)
您可以使用reset()动态重新分配auto_ptr,顺便说一下,它会破坏以前指向的对象实例。
但是,unique_ptr不推荐使用unique_ptr,它有一个swap()函数,它有点似乎坚持你正在寻找的东西。
请记住,这些类不是线程安全的。