可以安全地使用auto_ptr交换对象而无需在多线程环境中锁定?

时间:2013-01-05 19:08:29

标签: c++ multithreading performance copy-on-write

我在堆上分配了一些很少修改但需要快速读取访问权限的数据结构。一个例子是在堆上分配的结构,许多线程以只读方式非常频繁地访问该结构。这个结构需要定期重写并避免锁定争用我想知道使用auto_ptr是否可以安全地使用获取引用的线程继续处理直到它们完成但允许编写器生成结构的副本,重写它并快速交换指针与结构的新auto_ptr实例。

我从Java中的CopyOnWriteArrayList得到了这个想法,并希望在C ++中执行类似的性能。

2 个答案:

答案 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_loadatomic_storeatomic_exchange

制作shared_ptr的副本时,请使用atomic_load,并在更新shared_ptr时使用atomic_store

这样做很重要,原因有两个。

  1. atomic_ *操作为您提供了一种线程安全的方式来制作共享指针的副本。
  2. 制作副本意味着当全局共享指针发生更改时,您的副本仍然指向旧字符串,因此您的代码不必担心在不期望的情况下对其进行操作的数据进行更改。 / LI>

    现在,重要的是要注意在shared_ptr上使用线程安全操作不会为它指向的类型提供任何线程安全性。您始终必须注意所指向的对象是以线程安全的方式使用。

答案 1 :(得分:2)

您可以使用reset()动态重新分配auto_ptr,顺便说一下,它会破坏以前指向的对象实例。

但是,unique_ptr不推荐使用unique_ptr,它有一个swap()函数,它有点似乎坚持你正在寻找的东西。

请记住,这些类是线程安全的。