C++ 具有多线程的安全消息队列
以下是我的基本情况: 我有一个线程,它定期检查并处理消息 线程B和C需要向A发送消息 当B和C或B或C试图在a处理消息并访问队列时向a发送消息时,就会出现问题 这个问题通常是如何解决的C++ 具有多线程的安全消息队列,c++,multithreading,C++,Multithreading,以下是我的基本情况: 我有一个线程,它定期检查并处理消息 线程B和C需要向A发送消息 当B和C或B或C试图在a处理消息并访问队列时向a发送消息时,就会出现问题 这个问题通常是如何解决的 感谢这通常通过使用或其他多线程保护机制来解决 如果您在windows上工作,MFC提供了解决此问题的方法 如果您在posix系统上工作,POSIXAPI将提供 一些基本伪代码可以方便地在您的案例中演示它们的用法: pthread_mutex_t mutex; *or* CMutex mutex; Q queue;
感谢这通常通过使用或其他多线程保护机制来解决 如果您在windows上工作,MFC提供了解决此问题的方法 如果您在posix系统上工作,POSIXAPI将提供 一些基本伪代码可以方便地在您的案例中演示它们的用法:
pthread_mutex_t mutex; *or* CMutex mutex;
Q queue; // <-- both mutex and queue are global state, whether they are
// global variables, or passed in as parameters, they must
// be the shared by all threads.
int threadA(/* params */){
while( threadAStillRunning ){
// perform some non-critical actions ...
pthread_mutex_lock(mutex) *or* mutex.Lock()
// perform critical actions ...
msg = queue.receiveMessage()
pthread_mutex_unlock(mutex) *or* mutex.Unlock()
// perform more non-critical actions
}
}
int threadBorC(/* params */){
while( theadBorCStillRunning ){
// perform some non-critical actions ...
pthread_mutex_lock(mutex) *or* mutex.Lock()
// perform critical actions ...
queue.sendMessage(a_msg)
pthread_mutex_unlock(mutex) *or* mutex.Unlock()
}
}
pthread\u mutex\u t mutex*或*CMutex互斥体;
Q队列;//如果你不在Windows上或者如果你正在执行C++中的跨平台的东西,请尝试使用ACE库中的队列。p>
ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue;
ACE\u消息队列*msg\u队列;
作为ACE库示例中的示例,您可以使用
要将消息放入队列,请执行以下操作:
ACE_NEW_RETURN (mb,
ACE_Message_Block (rb.size (),
ACE_Message_Block::MB_DATA,
0,
buffer),
0);
mb->msg_priority (ACE_Utils::truncate_cast<unsigned long> (rb.size ()));
mb->wr_ptr (rb.size ());
ACE_DEBUG ((LM_DEBUG,
"enqueueing message of size %d\n",
mb->msg_priority ()));
// Enqueue in priority order.
if (msg_queue->enqueue_prio (mb) == -1)
ACE_ERROR ((LM_ERROR, "(%t) %p\n", "put_next"));
ACE_NEW_RETURN(mb,
ACE_消息_块(rb.size(),
ACE_消息_块::MB_数据,
0,
缓冲区),
0);
mb->msg_优先级(ACE_Utils::truncate_cast(rb.size());
mb->wr_ptr(rb.size());
ACE_调试((LM_调试,
“正在将大小为%d的消息排入队列\n”,
mb->msg_优先级());
//按优先顺序排队。
如果(消息队列->排队优先级(mb)=-1)
ACE_错误((LM_错误,(%t)%p\n,“下一步放置”);
要从队列中获取,请执行以下操作:
ACE_Message_Block *mb = 0;
msg_queue->dequeue_head (mb) == -1;
int length = ACE_Utils::truncate_cast<int> (mb->length ());
if (length > 0)
ACE_OS::puts (mb->rd_ptr ());
// Free up the buffer memory and the Message_Block.
ACE_Allocator::instance ()->free (mb->rd_ptr ());
mb->release ();
ACE\u消息块*mb=0;
消息队列->出列队列头(mb)=-1;
int length=ACE_Utils::truncate_cast(mb->length());
如果(长度>0)
ACE_OS::puts(mb->rd_ptr());
//释放缓冲内存和消息块。
ACE_分配器::实例()->free(mb->rd_ptr());
mb->release();
优点是您可以非常轻松地更改同步原语,而无需编写太多代码 Nate的回答是正确的,但请注意,虽然互斥体使用起来很简单,但它们可能不适合于非常高的吞吐量场景,因为它们的开销相对较高。啊,但线程通常也是如此;^)严肃地说,不同的平台在线程保护方面有不同的弱点;有一些人的互斥体是在内核中注册的(我在看你,windows),还有一些人的互斥体只是围绕原子检查的“包装器”(几乎不花什么钱)。@Nate:在windows上,你可能在寻找关键部分,它们也很便宜。@BenVoigt-是的,关键部分有这个优势(我非常喜欢他们),但是“习惯地”它们不应该用于数据保护,而只是用于从多个线程调用的不可重入的函数中。我想这就是为什么我没有提到它们。不过,如果你不介意打破这个习惯用法的话,它们是一个便宜的解决方案。@Nate:我从来没有听过关于批评家的哲学争论所有部分。它们通常用于数据同步。您是使用win32还是posix?这将帮助我清理我的小伪代码示例。