是boost shared_ptr吗? 线程安全?
我有关于 boost::shared_ptr
的问题。
有很多线程。
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
如果Thread_A不关心nowResource
是最新的,这部分代码会有问题吗?
我的意思是,当 Thread_B 没有完全 SetResource()
时,Thread_A 通过 GetResource()
得到错误的智能点?
Q2
线程安全是什么意思?
如果我不关心资源是否是最新的,那么 shared_ptr
在释放 nowResource
时使程序崩溃,或者该问题是否会破坏 shared_ptr
?
I have a question about boost::shared_ptr<T>
.
There are lots of thread.
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
If Thread_A do not care the nowResource
is the newest, will this part of code have problem?
I mean when Thread_B do not SetResource()
completely, Thread_A get a wrong smart point by GetResource()
?
Q2
What does thread-safe mean?
If I do not care about whether the resource is newest, will the shared_ptr<CResource> nowResource
crash the program when the nowResource
is released or will the problem destroy the shared_ptr<CResource>
?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
boost::shared_ptr
提供一定程度的线程安全性。 引用计数以线程安全的方式进行操作(除非您配置 boost 来禁用线程支持)。因此,您可以复制
shared_ptr
并正确维护 ref_count 。 在多线程中无法安全执行的操作是从多个线程修改实际的shared_ptr
对象实例本身(例如从多个线程调用reset()
)。 因此您的使用并不安全 - 您正在多个线程中修改实际的shared_ptr
实例 - 您需要拥有自己的保护。在我的代码中,
shared_ptr
通常是本地变量或按值传递的参数,因此没有问题。 将它们从一个线程转移到另一个线程我通常使用线程安全队列。当然,这些都没有解决访问
shared_ptr
指向的对象的线程安全性 - 这也取决于您。boost::shared_ptr<>
offers a certain level of thread safety. The reference count is manipulated in a thread safe manner (unless you configure boost to disable threading support).So you can copy a
shared_ptr
around and the ref_count is maintained correctly. What you cannot do safely in multiple threads is modify the actualshared_ptr
object instance itself from multiple threads (such as callingreset()
on it from multiple threads). So your usage is not safe - you're modifying the actualshared_ptr
instance in multiple threads - you'll need to have your own protection.In my code,
shared_ptr
's are generally locals or parameters passed by value, so there's no issue. Getting them from one thread to another I generally use a thread-safe queue.Of course none of this addresses the thread safety of accessing the object pointed to by the
shared_ptr
- that's also up to you.来自 boost 文档:
因此您的使用并不安全,因为它使用
m_res
的同时读写。 boost 文档中的示例 3 也说明了这一点。您应该使用单独的 互斥体< /a> 保护对
SetResource
/GetResource
中m_res
的访问。From the boost documentation:
So your usage is not safe, since it uses simultaneous read and write of
m_res
. Example 3 in the boost documentation also illustrates this.You should use a separate mutex that guards the access to
m_res
inSetResource
/GetResource
.嗯,tr1::shared_ptr(基于 boost)文档讲述了一个不同的故事,这意味着资源管理是线程安全的,而对资源的访问则不是。
“...
线程安全
中不推荐使用采用 auto_ptr 参数的构造函数。
C++0x 独有的功能包括:右值引用/移动支持、分配器支持、别名构造函数、make_shared 和 allocate_shared。此外,在 C++0x模式 Boost shared_ptr 文档的线程安全部分说“shared_ptr 对象提供与内置类型相同级别的线程安全性。”即使这些实例共享引用计数(例如,
shared_ptr a), 实现也必须确保对单独的 shared_ptr 实例的并发更新是正确的。 (新A);
共享指针 b(a);
// 线程 1 // 线程 2
a.reset(); b.重置();
动态分配的对象必须由其中一个线程销毁。 弱引用让事情变得更加有趣。 用于实现shared_ptr的共享状态必须对用户透明,并且必须始终保留不变量。 共享状态的关键部分是强引用计数和弱引用计数。 对这些的更新需要是原子的并且对所有线程可见,以确保托管资源的正确清理(毕竟,这是shared_ptr的工作!)在多处理器系统上,可能需要内存同步,以便引用计数更新和销毁的托管资源是无竞争的。
...“
看
http://gcc.gnu.org/onlinedocs /libstdc++/manual/memory.html#std.util.memory.shared_ptr
Well, tr1::shared_ptr (which is based on boost) documentation tells a different story, which implies that resource management is thread safe, whereas access to the resource is not.
"...
Thread Safety
C++0x-only features are: rvalue-ref/move support, allocator support, aliasing constructor, make_shared & allocate_shared. Additionally, the constructors taking auto_ptr parameters are deprecated in C++0x mode.
The Thread Safety section of the Boost shared_ptr documentation says "shared_ptr objects offer the same level of thread safety as built-in types." The implementation must ensure that concurrent updates to separate shared_ptr instances are correct even when those instances share a reference count e.g.
shared_ptr a(new A);
shared_ptr b(a);
// Thread 1 // Thread 2
a.reset(); b.reset();
The dynamically-allocated object must be destroyed by exactly one of the threads. Weak references make things even more interesting. The shared state used to implement shared_ptr must be transparent to the user and invariants must be preserved at all times. The key pieces of shared state are the strong and weak reference counts. Updates to these need to be atomic and visible to all threads to ensure correct cleanup of the managed resource (which is, after all, shared_ptr's job!) On multi-processor systems memory synchronisation may be needed so that reference-count updates and the destruction of the managed resource are race-free.
..."
see
http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr
m_Res 不是线程安全的,因为它同时读/写,
你需要 boost::atomic_store/load 函数来保护它。
m_Res is not threadsafe ,because it simultaneous read/write,
you need boost::atomic_store/load function to protects it.
添加,你的类有一个循环引用条件;
shared_ptr; m_Res
不能是CResourceBase
的成员。 您可以使用weak_ptr
代替。Add, your class has a Cyclic-references condition; the
shared_ptr<CResource> m_Res
can't be a member ofCResourceBase
. You can useweak_ptr
instead.