C++ boost shared_ptr <XXX> 线程安全吗?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/692438/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Is boost shared_ptr <XXX> thread safe?
提问by user25749
I have a question about boost::shared_ptr<T>
.
我有一个关于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_Ado not care the nowResource
is the newest, will this part of code have problem?
如果Thread_A不关心nowResource
是最新的,这部分代码会不会有问题?
I mean when Thread_Bdo not SetResource()
completely, Thread_Aget a wrong smart point by GetResource()
?
我的意思是当Thread_B不SetResource()
完全时,Thread_A得到一个错误的智能点GetResource()
?
Q2
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>
?
如果我不关心资源是否是最新的,释放shared_ptr<CResource> nowResource
时会导致程序崩溃nowResource
还是问题会破坏shared_ptr<CResource>
?
回答by Michael Burr
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).
boost::shared_ptr<>
提供一定程度的线程安全。引用计数以线程安全的方式操作(除非您配置 boost 以禁用线程支持)。
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 actual shared_ptr
object instance itself from multiple threads (such as calling reset()
on it from multiple threads). So your usage is not safe - you're modifying the actual shared_ptr
instance in multiple threads - you'll need to have your own protection.
所以你可以复制 ashared_ptr
并且正确维护 ref_count 。在多线程中不能安全地做的是shared_ptr
从多个线程修改实际对象实例本身(例如从多个线程调用reset()
它)。所以你的使用是不安全的——你shared_ptr
在多个线程中修改实际实例——你需要有自己的保护。
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.
在我的代码中,shared_ptr
's 通常是局部变量或按值传递的参数,因此没有问题。让他们从一个线程到另一个我通常使用线程安全队列。
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.
当然,这些都没有解决访问指向的对象的线程安全问题shared_ptr
——这也取决于你。
回答by sth
From the boost documentation:
从提升文档:
shared_ptr
objects offer the same level of thread safety as built-in types. Ashared_ptr
instance can be "read" (accessed using only const operations) simultaneously by multiple threads. Differentshared_ptr
instances can be "written to" (accessed using mutable operations such asoperator=
or reset) simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.)Any other simultaneous accesses result in undefined behavior.
shared_ptr
对象提供与内置类型相同级别的线程安全。一个shared_ptr
实例可以被多个线程同时“读取”(仅使用 const 操作访问)。不同的shared_ptr
实例可以operator=
由多个线程同时“写入”(使用可变操作如或 reset访问)(即使这些实例是副本,并且在下面共享相同的引用计数。)任何其他同时访问都会导致未定义的行为。
So your usage is not safe, since it uses simultaneous read and write of m_res
. Example 3in the boost documentation also illustrates this.
所以你的使用是不安全的,因为它同时使用m_res
. boost 文档中的示例 3也说明了这一点。
You should use a separate mutexthat guards the access to m_res
in SetResource
/GetResource
.
您应该使用一个单独的互斥锁来保护对m_res
in SetResource
/的访问GetResource
。
回答by YoavT
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.
嗯,tr1::shared_ptr(基于 boost)文档讲述了一个不同的故事,这意味着资源管理是线程安全的,而对资源的访问不是。
"...
“……
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.
C++0x-only 特性是:rvalue-ref/move 支持、分配器支持、别名构造函数、make_shared 和allocate_shared。此外,在 C++0x 模式下不推荐使用 auto_ptr 参数的构造函数。
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.
Boost shared_ptr 文档的线程安全部分说“shared_ptr 对象提供与内置类型相同级别的线程安全。” 实现必须确保对单独 shared_ptr 实例的并发更新是正确的,即使这些实例共享一个引用计数,例如
shared_ptr a(new A); shared_ptr b(a);
shared_ptr a(new A); shared_ptr b(a);
// Thread 1 // Thread 2
// 线程 1 // 线程 2
a.reset(); b.reset();
a.reset(); b.重置();
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.
动态分配的对象必须正好被其中一个线程销毁。弱引用使事情变得更加有趣。用于实现 shared_ptr 的共享状态必须对用户透明,并且必须始终保留不变量。共享状态的关键部分是强引用和弱引用计数。对这些的更新需要是原子的并且对所有线程可见,以确保正确清理托管资源(毕竟,这是 shared_ptr 的工作!)在多处理器系统上可能需要内存同步,以便引用计数更新和销毁的托管资源是无竞争的。
..."
……”
see http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr
见 http://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.shared_ptr
回答by xpfans
m_Resis not threadsafe ,because it simultaneous read/write, you need boost::atomic_store/load function to protects it.
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
回答by tntvampire
Add, your class has a Cyclic-references condition; the shared_ptr<CResource> m_Res
can't be a member of CResourceBase
. You can use weak_ptr
instead.
补充一下,你的班级有一个循环引用条件;在shared_ptr<CResource> m_Res
不能的成员CResourceBase
。你可以weak_ptr
改用。