Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 具有多线程的安全消息队列_C++_Multithreading - Fatal编程技术网

C++ 具有多线程的安全消息队列

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;

以下是我的基本情况:

我有一个线程,它定期检查并处理消息

线程B和C需要向A发送消息

当B和C或B或C试图在a处理消息并访问队列时向a发送消息时,就会出现问题

这个问题通常是如何解决的


感谢

这通常通过使用或其他多线程保护机制来解决

如果您在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?这将帮助我清理我的小伪代码示例。