简体   繁体   English

boost shared_ptr <XXX>线程安全吗?

[英]Is boost shared_ptr <XXX> thread safe?

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 Q1

If Thread_A do not care the nowResource is the newest, will this part of code have problem? 如果Thread_A不关心nowResource是最新的,那么这部分代码会有问题吗?

I mean when Thread_B do not SetResource() completely, Thread_A get 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> ? 如果我不关心资源是否是最新的,那么当nowResource被释放时, shared_ptr<CResource> nowResource会使程序崩溃,或者问题是否会破坏shared_ptr<CResource>

boost::shared_ptr<> offers a certain level of thread safety. boost::shared_ptr<>提供一定程度的线程安全性。 The reference count is manipulated in a thread safe manner (unless you configure boost to disable threading support). 引用计数以线程安全方式进行操作(除非您将boost配置为禁用线程支持)。

So you can copy a shared_ptr around and the ref_count is maintained correctly. 因此,您可以复制shared_ptr并正确维护ref_count。 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). 你不能在多个线程中安全地做的是从多个线程修改实际的shared_ptr对象实例本身(例如从多个线程调用reset() )。 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. 因此,您的使用不安全 - 您正在修改多个线程中的实际shared_ptr实例 - 您需要拥有自己的保护。

In my code, shared_ptr 's are generally locals or parameters passed by value, so there's no issue. 在我的代码中, shared_ptr通常是按值传递的本地或参数,因此没有问题。 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. 当然,这些都不能解决访问shared_ptr指向的对象的线程安全问题 - 这也取决于您。

From the boost documentation : 从boost 文档

shared_ptr objects offer the same level of thread safety as built-in types. shared_ptr对象提供与内置类型相同的线程安全级别。 A shared_ptr instance can be "read" (accessed using only const operations) simultaneously by multiple threads. 可以通过多个线程同时“读取”(仅使用const操作访问) shared_ptr实例。 Different shared_ptr instances can be "written to" (accessed using mutable operations such as operator= or reset) simultaneously by multiple threads (even when these instances are copies, and share the same reference count underneath.) 可以通过多个线程同时“写入”(使用诸如operator=或reset之类的可变操作来访问) 不同的 shared_ptr实例(即使这些实例是副本,并在下面共享相同的引用计数。)

Any other simultaneous accesses result in undefined behavior. 任何其他同时访问都会导致未定义的行为。

So your usage is not safe, since it uses simultaneous read and write of m_res . 因此,您的使用不安全,因为它使用m_res同时读写。 Example 3 in the boost documentation also illustrates this. boost文档中的示例3也说明了这一点。

You should use a separate mutex that guards the access to m_res in SetResource / GetResource . 您应该使用一个单独的互斥锁来保护对SetResource / GetResource m_res的访问。

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. C ++ 0x-only功能包括:rvalue-ref / move支持,分配器支持,别名构造函数,make_shared和allocate_shared。 Additionally, the constructors taking auto_ptr parameters are deprecated in C++0x mode. 此外,采用auto_ptr参数的构造函数在C ++ 0x模式下已弃用。

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." Boost shared_ptr文档的Thread Safety部分说“shared_ptr对象提供与内置类型相同的线程安全级别。” The implementation must ensure that concurrent updates to separate shared_ptr instances are correct even when those instances share a reference count eg 实现必须确保对单独的shared_ptr实例的并发更新是正确的,即使这些实例共享引用计数,例如

shared_ptr a(new A); shared_ptr a(新A); shared_ptr b(a); shared_ptr b(a);

// Thread 1 // Thread 2 //线程1 //线程2

a.reset(); a.reset(); b.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. 用于实现shared_ptr的共享状态必须对用户透明,并且必须始终保留不变量。 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的工作!)在多处理器系统上,可能需要内存同步,以便引用计数更新和销毁托管资源是无竞争的。

..." ......”

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

m_Res is 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

Add, your class has a Cyclic-references condition; 添加,您的类具有循环引用条件; the shared_ptr<CResource> m_Res can't be a member of CResourceBase . shared_ptr<CResource> m_Res不能是CResourceBase的成员。 You can use weak_ptr instead. 您可以改用weak_ptr

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM