这是我的本质所在:
我有线程A定期检查消息并处理它们。
线程B和C需要向A发送消息。
当A处理消息并因此访问队列时,B和C或B或C尝试向A发送消息时出现问题。
这个问题通常如何解决?
谢谢
答案 0 :(得分:4)
这通常使用mutexes或其他多线程保护机制来解决。
如果您正在使用Windows,MFC会为此问题提供CMutex class。
如果您正在使用posix系统,posix api会提供pthread_mutex_lock
, pthread_mutex_unlock
, and pthread_mutex_trylock
functions。
一些基本的伪代码可以方便地展示它们在你的情况下的使用:
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()
}
}
对于所有三个线程,它们在队列中执行的能力取决于它们获取互斥锁的能力 - 它们将简单地阻塞并等待直到获取互斥锁。这可以防止因使用该资源而产生的冲突。
答案 1 :(得分:0)
如果您不在Windows上或者在C ++中实现跨平台的东西,请尝试使用ACE库中的Queue。
ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue;
作为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_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 ();
优点是您可以非常轻松地更改同步原语,而无需编写太多代码。