2011-10-16 40 views
6

Đây là những gì tôi về cơ bản có:Hàng đợi tin nhắn an toàn với nhiều chủ đề

Tôi có chủ đề A định kỳ kiểm tra thư và xử lý chúng.

Chủ đề B và C cần phải gửi tin nhắn cho A.

Vấn đề nảy sinh khi B và C hoặc B hoặc C cố gắng gửi một thông điệp tới Một khi A được xử lý một thông điệp và do đó truy cập vào hàng đợi.

Sự cố này thường được giải quyết như thế nào?

Cảm ơn

+0

bạn có đang làm việc với win32 hoặc posix không? Nó sẽ giúp tôi làm sạch ví dụ giả nhỏ của tôi. – Nate

Trả lời

4

này thường được giải quyết bằng mutexes, hoặc các cơ chế bảo vệ multi-thread khác.

Nếu bạn đang làm việc trên các cửa sổ, MFC cung cấp CMutex class cho sự cố này.

Nếu bạn đang làm việc trên hệ thống posix, posix api cung cấp pthread_mutex_lock, pthread_mutex_unlock, and pthread_mutex_trylock functions.

Một số giả cơ bản sẽ được thuận tiện để chứng minh việc sử dụng chúng trong trường hợp của bạn:

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

Đối với tất cả ba chủ đề, khả năng hoạt động trên hàng đợi bản lề đối với khả năng của họ để có được các mutex - họ sẽ chỉ đơn giản là khối và chờ cho đến khi có được mutex. Điều này ngăn cản xung đột phát sinh từ việc sử dụng tài nguyên đó.

+0

Câu trả lời của Nate là chính xác, nhưng lưu ý rằng mặc dù các mutex rất dễ sử dụng, chúng có thể không phù hợp với các kịch bản thông lượng rất cao vì chúng có chi phí khá cao. –

+0

Ah, nhưng do đó, làm chủ đề nói chung; ^) Nghiêm túc, mặc dù nền tảng khác nhau có điểm yếu khác nhau khi nói đến thread-bảo vệ; có một số trong đó có mutexes được đăng ký với hạt nhân (tôi đang nhìn bạn, cửa sổ), và những người khác, nơi mutexes chỉ là "wrappers" xung quanh kiểm tra nguyên tử (mà hầu như không chi phí một điều). – Nate

+0

@Nate: Trên Windows, có thể bạn đang tìm kiếm Các phần quan trọng, cũng rất rẻ. –

0

Nếu bạn không ở trên cửa sổ hoặc nếu bạn đang triển khai một cái gì đó là nền tảng chéo trong C++, hãy thử sử dụng Hàng đợi từ thư viện ACE.

ACE_Message_Queue<ACE_MT_SYNCH> *msg_queue; 

Là một mẫu từ các mẫu thư viện ACE, Sau đó, bạn có thể sử dụng Đối với việc đưa thông điệp tới hàng đợi:

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

để nhận từ hàng đợi:

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

Ưu điểm là bạn có thể thay đổi đồng bộ nguyên thủy rất dễ dàng mà không cần phải viết quá nhiều mã.

Các vấn đề liên quan