簡體   English   中英

具有多個線程的安全消息隊列

[英]Safe Message Queue with multiple threads

這是我基本上擁有的:

我有線程A定期檢查消息並處理它們。

線程B和C需要向A發送消息。

當A正在處理消息並因此訪問隊列時,B和C或B或C嘗試向A發送消息時出現問題。

這個問題通常如何解決?

謝謝

這通常使用互斥鎖或其他多線程保護機制來解決。

如果您正在使用Windows,MFC會為此問題提供CMutex類

如果您正在使用posix系統,posix api會提供pthread_mutex_lockpthread_mutex_unlockpthread_mutex_trylock函數

一些基本的偽代碼可以方便地展示它們在你的情況下的用法:

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()
    }
}

對於所有三個線程,它們在隊列上行動的能力取決於它們獲取互斥鎖的能力 - 它們將簡單地阻塞並等待直到獲取互斥鎖。 這可以防止因使用該資源而產生的沖突。

如果您不在Windows上或者在C ++中實現跨平台的東西,請嘗試使用ACE庫中的Queue。

ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue;

作為ACE庫樣本的示例,您可以使用For將消息放入隊列:

  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 ();

優點是您可以非常輕松地更改同步原語,而無需編寫太多代碼。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM