我有一个问题 boost::shared_ptr<T>.

有很多线程。

using namespace boost;

class CResource
{
  // xxxxxx
}

class CResourceBase
{
public:
   void SetResource(shared_ptr<CResource> res)
   {
     m_Res = res;
   }

   shared_ptr<CResource> GetResource()
   {
      return m_Res;
   }
private:
   shared_ptr<CResource> m_Res;
}

CResourceBase base;

//----------------------------------------------
// Thread_A:
    while (true)
    {
       //...
       shared_ptr<CResource> nowResource = base.GetResource();
       nowResource.doSomeThing();
       //...
    }

// Thread_B:
    shared_ptr<CResource> nowResource;
    base.SetResource(nowResource);
    //...

Q1

如果 线程_A 不在乎 nowResource 是最新的,这部分代码会不会有问题?

我的意思是当 线程_B 不要 SetResource() 完全地, 线程_A 得到错误的智能点 GetResource()?

Q2

线程安全是什么意思?

如果我不关心资源是否是最新的, shared_ptr<CResource> nowResourcenowResource 被释放还是问题会毁掉 shared_ptr<CResource>?

有帮助吗?

解决方案

来自助推 文档:

shared_ptr 对象提供与内置类型相同的线程安全性。A shared_ptr 可以通过多个线程同时“读取”实例(仅使用const操作访问)。 不同的 shared_ptr 实例可以“写入”(使用可变操作访问,例如 operator= 或通过多个线程同时重置)(即使这些实例是副本,并在下面共享相同的参考计数。)

任何其他同时访问都会导致未定义的行为。

所以你的使用是不安全的,因为它使用同时读写 m_res. 实施例3 boost文档中也说明了这一点。

你应该使用一个单独的 互斥量 保护对的访问 m_resSetResource/GetResource.

其他提示

boost::shared_ptr<> 提供一定程度的线程安全。引用计数以线程安全的方式进行操作(除非您配置 boost 来禁用线程支持)。

所以你可以复制一个 shared_ptr 周围并且 ref_count 保持正确。在多线程中你不能安全地做的是修改实际的 shared_ptr 来自多个线程的对象实例本身(例如调用 reset() 来自多个线程)。所以你的使用是不安全的 - 你正在修改实际的 shared_ptr 多个线程中的实例 - 您需要有自己的保护。

在我的代码中, shared_ptr通常是本地变量或按值传递的参数,因此没有问题。将它们从一个线程转移到另一个线程我通常使用线程安全队列。

当然,这些都没有解决访问该对象所指向的对象的线程安全性。 shared_ptr - 这也取决于你。

嗯,tr1::shared_ptr(基于 boost)文档讲述了一个不同的故事,这意味着资源管理是线程安全的,而对资源的访问则不是。

"...

线程安全

仅 C++0x 的功能包括:rvalue-ref/move 支持、分配器支持、别名构造函数、make_shared 和 allocate_shared。此外,在 C++0x 模式下不推荐使用 auto_ptr 参数的构造函数。

Boost shared_ptr文档的线程安全部分说“共享_ptr对象提供与内置类型相同的线程安全性”。实现必须确保即使这些实例共享参考计数,也可以确保对单独的共享_ptr实例的并发更新,例如

Shared_ptr a(新A);共享指针 b(a);

// 线程 1 // 线程 2

a.重置();b.重置();

动态分配的对象必须由其中一个线程销毁。弱引用让事情变得更加有趣。用于实现shared_ptr的共享状态必须对用户透明,并且必须始终保留不变量。共享状态的关键部分是强引用计数和弱引用计数。对这些的更新需要是原子的并且对所有线程可见,以确保托管资源的正确清理(毕竟,这是shared_ptr的工作!)在多处理器系统上,可能需要内存同步,以便引用计数更新和销毁的托管资源是无竞争的。

..."

http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr

m_Res 不是螺纹安全,因为它同时读/写,您需要boost :: atomic_store/load函数来保护它。

//--- Example 3 ---
// thread A
p = p3; // reads p3, writes p
// thread B
p3.reset(); // writes p3; undefined, simultaneous read/write

添加,你的类有一个循环引用条件;这 shared_ptr<CResource> m_Res 不能成为以下成员 CResourceBase. 。您可以使用 weak_ptr 反而。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top