【问题标题】:Passing messages between threads and memory management在线程和内存管理之间传递消息
【发布时间】:2013-04-17 01:15:23
【问题描述】:

我正在编写一个带有两个线程的 C++ 应用程序。线程 A 将向线程 B 发送消息。消息类型可以是:

struct MyMessageType
{
  int a;
  enum MyEnum b;
  bool someFlag;
}

std::queue<MyMessageType> messageQueue 在线程之间共享用于传递消息。

在发送线程中,我会有类似的东西:

struct MyMessageType newMessage;
newMessage.a = 14;
newMessage.b = someEnumeratedValue;
newMessage.someFlag = false;
GrabTheMutexProtectingTheQueue();
messageQueue.push(newMessage);
ReleaseTheMutexProtectingTheQueue();

我的问题是关于内存管理的,有两个方面:

A) 如何确保接收线程收到消息时指向newMessage 的指针有效?例如,如果创建newMessage 的函数结束并且newMessage 因此在接收线程处理消息之前超出范围会发生什么?

B) 一旦我可以确保newMessage 指针在接收线程处理它时有效,我如何释放结构使用的内存?

【问题讨论】:

  • C 中没有 std::queue。也许你的意思是 C++?

标签: c++ multithreading memory-management


【解决方案1】:

std::queuepush() 函数存储您提供的任何内容的副本(请参阅 here),因此您不必担心它超出范围。 p>

队列中的副本将继续存在,直到您使用 pop() 将其删除。

所以,在发送方,这是一个简单的问题(例如):

lock_mutex();
myqueue.push (something);
unlock_mutex();
// Do whatever you want with something, the queue has a copy

并且,在接收端:

lock_mutex();
while (myqueue.empty()) {
    unlock_mutex();
    // possibly yield to another thread
    lock_mutex();
}
something = myqueue.front();
weaveMagicWith (something);
myqueue.pop();
unlock_mutex();

当然,您可以重新设计它以最小化接收端互斥锁的持续时间(例如,如果编织魔法需要很长时间),这只是一个粗略的示例,展示了一种方法。

【讨论】:

  • +1 是的。当消息很小时,使用指针类型作为模板参数是没有意义的。指针类型仅在消息较大时才有用(例如磁盘/网络缓冲区)。
  • 如果 weaveMagicWith() 可能需要一些时间,最好在释放互斥体后执行。 front() 调用制作了数据的另一个副本,因此在 weaveMagicWith() 之前调用 pop() 是安全的。
  • 对吗,@brian?文档声明它返回对队列中第一个项目的引用。那不是副本,是吗? MS 文档也支持这一点:“如果将 front 的返回值分配给引用,则可以修改队列对象”。
  • 如何使用 atomic<:queue>> 来避免互斥调用?
  • @Damian 我知道这有点晚了,但为了将来参考......不,这不是它的工作原理。查看this答案以获得更详细的解释。
猜你喜欢
  • 1970-01-01
  • 2021-03-27
  • 2011-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-30
  • 1970-01-01
相关资源
最近更新 更多