【发布时间】:2020-04-02 17:34:47
【问题描述】:
所以我试图通过我正在使用的消息传递机制在线程之间传递一个共享指针。由于序列化/反序列化的工作方式,我无法将 shared_ptr 直接嵌入到我发送的消息中。所以我实际上需要发送一个 shared_ptr 的原始指针。见下文:
线程 1:
auto objPtr = std::make_shared<ObjectClass>();
uint64_t serializedPtr = reinterpret_cast<uint64_t>(&objPtr);
线程 2:
std::shared_ptr<ObjectClass> objPtrT2 = *(reinterpret_cast<std::shared_ptr<ObjectClass>*>(serializedPtr));
这有时会在线程 2 中在增加共享指针的引用计数时崩溃。我只能假设这里有一些竞争条件,但无法找出解决方案。请注意,它并不总是崩溃,反序列化似乎总是成功的。
我是否需要同步对此 shared_ptr 的访问(shared_ptr 本身,而不是 share_ptr 指向的内容)?我担心我传输此 shared_ptr 的方式会破坏引用计数的管理方式。
出于其他与性能相关的原因,我仍在争论在此处使用 shared_ptr 是否合适,但为了我自己的利益,我想知道我做错了什么。
谢谢
编辑: 请注意,线程 1 和线程 2 位于同一进程/主机中。我将 shared_ptr 放置到由 thread1 管理的地图中(我试图省略我最初认为不重要的细节)。然而,我没有意识到的是,我从所述地图中检索的方式是不正确的。我将地图的内容复制到临时 shared_ptr 中,然后将临时 shared_ptr 的地址发送到 thread2。所以我无意中发送了堆栈上变量的地址。愚蠢的错误,但我认为这个帖子中的评论仍然很有启发性/有帮助。以下似乎解决了我的问题。
auto& objPtr = m_objMap[index];
uint64_t serializedPtr = reinterpret_cast<uint64_t>(&objPtr);
【问题讨论】:
-
为什么需要序列化?线程共享内存;为什么不直接传递共享指针?
-
是的,我同意。我在这里省略了一些细节。 objPtr 存储在线程 1 中维护的映射中。线程 2 将 shared_ptr 存储/维护在不同的数据结构中。所以对象不应该被破坏(尽管我将通过调试器进行验证)。
-
@AndrewP 请注意,您传递的是指向
shared_ptr<T>而不是T的指针,因此实际的shared_ptr需要仍然存在。确保您的容器没有使其迭代器失效并且没有被移动。 -
是的,如果
shared_ptr在两个或多个线程之间共享后可以被任何线程修改,您确实需要同步访问。 -
两个线程是否在同一个进程中?
标签: c++ multithreading thread-safety shared-ptr race-condition