简体   繁体   English

boost :: interprocess :: shared_ptr threadsafe(和进程间安全)?

[英]Is boost::interprocess::shared_ptr threadsafe (and interprocess-safe)?

I want to share data between threads, and have it automatically deleted when the last user is done with it. 我想在线程之间共享数据,并在最后一个用户完成后自动删除它。 This seems to work, most of the time, using boost::interprocess::shared_ptr in a boost::fixed_managed_shared_memory segment: but not always. 大多数情况下,这似乎在boost::fixed_managed_shared_memory段中使用boost::interprocess::shared_ptr :但并非总是如此。

So, is boost::interprocess::shared_ptr thread (and interprocess) -safe? 那么,是boost::interprocess::shared_ptr线程(和进程间)-safe?

If I'm using my shared memory at a fixed address (I'm pretty certain this is going to be okay in my 64-bit (well, 48-bit) address space), is it possible to use a normal boost::shared_ptr (which are threadsafe) instead? 如果我在固定地址使用我的共享内存(我很确定这在我的64位(井,48位)地址空间中可以正常),是否可以使用普通的boost::shared_ptr而不是boost::shared_ptr (线程安全)?

some clarification: 一些澄清:

The pointer type I use is plain void* , (my shared memory is mapped to a fixed address). 我使用的指针类型是plain void* ,(我的共享内存映射到固定地址)。

The question of threadsafety is about the reference count -- ie, whether copying/destroying shared pointers to the same thing in different processes at the same time is permitted. 线程安全的问题是关于引用计数 - 即,是否允许同时复制/销毁在不同进程中同一事物的共享指针。 Not access to the same shared pointer in different threads, and not access to the pointee. 不能访问不同线程中的相同共享指针,也不能访问指针。

The reference count used in boost::interprocess:shared_ptr is implemented using an atomic counter defined in boost/interprocess/detail/atomic.hpp with the refcount logic mainly implemented by boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp . boost::interprocess:shared_ptr中使用的引用计数是使用boost/interprocess/detail/atomic.hpp定义的原子计数器实现的, boost/interprocess/detail/atomic.hpp逻辑主要由boost/interprocess/smart_ptr/detail/sp_counted_base_atomic.hpp The intent is to have the refcount be handled in a thread (and interprocess) safe manner. 目的是以线程(和进程间)安全的方式处理引用计数。

The atomic operation implementations differ depending on the specific target platform (Windows uses the Win32 Interlocked APIs, some platforms use various inline assembly, etc). 原子操作实现因具体目标平台而异(Windows使用Win32 Interlocked API,某些平台使用各种内联汇编等)。 It might be helpful to know what platform you're targeting. 了解您要定位的平台可能会有所帮助。 I suppose that you may be running into a bug in the refcount handling, though I wouldn't count on it. 我想你可能会遇到refcount处理中的错误,尽管我不会指望它。

I've restricted the above answer to the area you wanted specifically addressed: 我已经将上述答案限制在你想要专门解决的领域:

The question of threadsafety is about the reference count -- ie, whether copying/destroying shared pointers to the same thing in different processes at the same time is permitted. 线程安全的问题是关于引用计数 - 即,是否允许同时复制/销毁在不同进程中同一事物的共享指针。 Not access to the same shared pointer in different threads, and not access to the pointee. 不能访问不同线程中的相同共享指针,也不能访问指针。

That said, I'd look at bugs introduced possibly by the items you mention above or by somehow creating 'independent' boost::interprocess:shared_ptr objects (where different shared_ptr s refer to the same object using different refcounts). 也就是说,我会查看可能由您在上面提到的项目引入的错误,或者通过某种方式创建“独立” boost::interprocess:shared_ptr对象(其中不同的shared_ptr使用不同的refcounts引用相同的对象)。 This situation can be easy to have happen if you have some code that continues to use and/or pass around the raw object pointer. 如果你有一些代码继续使用和/或传递原始对象指针,这种情况很容易发生。

boost::shared_ptr<T> is not interprocess safe, so whether it is multithread safe in this context is moot. boost::shared_ptr<T>不是进程间安全的,所以在这种情况下它是否是多线程安全的是没有实际意义的。 (This statement assumes that BOOST_SP_DISABLE_THREADS has not been #defined for the program's operation.) (该陈述假定BOOST_SP_DISABLE_THREADS未被#defined用于程序的操作。)

boost::interprocess::shared_ptr<T> is, in its very nature, designed to be cross-process safe, as well as multithread safe in its nature. boost::interprocess::shared_ptr<T>就其本质而言,设计为跨进程安全,以及其本质上的多线程安全。 When the last reference goes out of scope, the pointed-at object can be cleaned up. 当最后一个引用超出范围时,可以清除指向的对象。 Obviously, this cleaning up happens within the bounds of the shared memory segment used for the object. 显然,这种清理发生在用于对象的共享内存段的范围内。

Since boost::shared_ptr<T> uses a lock-free counting mechanism at version 1.33.0 on many platforms, it is unlikely except by the remotest of chances that cross-process deletion of an object in a shared_memory segment would succeed, and does not appear to be supported functionality by the Boost maintainers. 由于boost::shared_ptr<T>在许多平台上使用1.33.0版本的无锁计数机制 ,因此除了最有可能在shared_memory段中跨对象删除对象成功的可能性之外,它是不可能的。似乎Boost维护者不支持这些功能。

Er. 呃。 boost::shared_ptr is most definitely not thread-safe. boost::shared_ptr绝对不是线程安全的。 At least not more thread-safe than eg std::vector . 至少不比例如std::vector更安全。 You may read a boost::shared_ptr from multiple threads, but as soon as any thread is writing a boost::shared_ptr it must synchronize with other writers and readers. 您可以从多个线程读取boost::shared_ptr ,但只要任何线程正在编写boost::shared_ptr它就必须与其他编写器读取器同步。

And no, you can not use it in shared memory, it was never designed to be. 不,你不能在共享内存中使用它,它从来没有设计过。 Eg it uses a so called "shared count" object that stores the reference-count and the deleter, and that shared-count object is allocated by the shared_ptr code, so it will not reside in shared memory. 例如,它使用一个所谓的“共享计数”对象来存储引用计数和删除器,并且该共享计数对象由shared_ptr代码分配,因此它不会驻留在共享内存中。 Also the shared_ptr code (and meta data like vtables) might be at totally different addresses in different processes, so any virtual function call would also be a problem (and IIRC shared_ptr uses virtual functions internally - or at least function pointers, which leads to the same problem). 此外, shared_ptr代码(以及类似vtable的元数据)可能在不同进程中处于完全不同的地址,因此任何虚函数调用也都是一个问题(IIRC shared_ptr在内部使用虚函数 - 或者至少是函数指针,这导致同样的问题)。


I don't know if boost::interprocess::shared_ptr is interprocess-safe, but I'm pretty sure it's not. 我不知道 boost::interprocess::shared_ptr是否是进程间安全的,但我很确定它不是。 Interprocess synchronization is pretty expensive. 进程间同步非常昂贵。 Having boost::interprocess::shared_ptr not do it makes it possible for the user to block accesses to shared data. 拥有boost::interprocess::shared_ptr 这样做能够为用户阻止访问共享数据。 That way the high synchronization cost only has to be paid once for multiple accesses in a row. 这样,对于连续多次访问,只需支付一次高同步成本。

EDIT: I would expect that the usage pattern that Eamon Nerbonne refered to in his comment (which is thread-safe with boost::shared_ptr ), is also OK with boost::interprocess::shared_ptr . 编辑:我希望 Eamon Nerbonne在他的评论中提到的使用模式(使用boost::shared_ptr是线程安全的),对于boost::interprocess::shared_ptr也是可以的。 Can't say for sure though. 虽然不能肯定地说。

"This seems to work, most of the time, using boost::interprocess::shared_ptr in a boost::fixed_managed_shared_memory segment: but not always." “大多数情况下,这似乎在boost :: fixed_managed_shared_memory段中使用boost :: interprocess :: shared_ptr:但并非总是如此。” If not always means that deletion don't work always: Just use a semaphore with your thread safe container. 如果并不总是意味着删除总是不起作用:只需使用一个信号量与您的线程安全容器。 This semaphore is not improve thread safety, but you can verify and even limit how many user use the data. 此信号量不会提高线程安全性,但您可以验证甚至限制用户使用数据的数量。 If semaphore is 0, then no more user, safe delete the shared data. 如果信号量为0,则不再有用户,安全删除共享数据。 If only one user there, this will be 1, so copy out the user-requested data, delete the shared container, then return with the copy. 如果那里只有一个用户,则为1,因此请复制出用户请求的数据,删除共享容器,然后返回副本。

Looking through the code in shared_ptr.hpp, and at the docs on the boost website, it would seem as though dereferencing a single instance may or may not be threadsafe depending on the second template parameter, which determines the internal pointer type to be used. 通过查看shared_ptr.hpp中的代码以及boost网站上的文档,似乎解除引用单个实例可能是也可能不是线程安全,具体取决于第二个模板参数,该参数决定了要使用的内部指针类型。 Specifically, "The internal pointer will be of the same pointer type as typename VoidAllocator::pointer type (that is, if typename VoidAllocator::pointer is offset_ptr, the internal pointer will be offset_ptr)." 具体来说,“内部指针与typename VoidAllocator :: pointer类型具有相同的指针类型(即,如果typename VoidAllocator :: pointer为offset_ptr,则内部指针将为offset_ptr)。” And since dereferences merely return the result of get()/get_pointer() method of this class, it should probably depend entirely on that. 由于dereferences只返回此类的get()/ get_pointer()方法的结果,它应该完全取决于它。 Boost::shared_ptr will work if you want simultaneous read-only access. 如果您想要同时进行只读访问,Boost :: shared_ptr将起作用。 For write access from multiple threads, you might have to write your own wrapper modelled after offset_ptr. 对于来自多个线程的写访问,您可能必须在offset_ptr之后编写自己的包装器。

As pgroke alludes to (not sure why the downvotes) the core question is whether you are accessing the same shared_ptr instance from different threads or processes. 正如pgroke暗示(不确定为什么是downvotes)核心问题是你是否从不同的线程或进程访问同一个 shared_ptr实例。

shared_ptr (interprocess or not) does not support this scenario, and this will not be safe. shared_ptr(进程间或非进程)不支持此方案,这不安全。

On the other hand, shared_ptr is designed to have multiple (thread-private, or protected from concurrent modification via some other mechanism) shared pointer instances point to the same object, and have different instances of these pointers to the same object be modified concurrently without issue. 另一方面,shared_ptr被设计为具有多个(线程私有,或通过某些其他机制来防止并发修改)共享指针实例指向同一对象,并且同时修改这些指向同一对象的不同实例问题。

::interprocess:: here is mostly a red-herring - it doesn't change the thread-safety of the pointer, just makes sure there are no internal pointers that refer to process-private memory, etc. :: interprocess ::这里主要是一个red-herring - 它不会改变指针的线程安全性,只是确保没有内部指针引用进程私有内存等。

So which of the two cases is it? 那两个案例中的哪一个呢?

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

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