boost shared_ptr <XXX> 线程安全吗?
-
22-08-2019 - |
题
我有一个问题 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> nowResource
当 nowResource
被释放还是问题会毁掉 shared_ptr<CResource>
?
其他提示
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
反而。