2014-02-13 107 views
1

這是正確的方式來製作一個線程安全隊列在C++中可以處理無符號字符*數組的二進制數據嗎?在C++中的線程安全隊列

請注意,在將數據從主線程產生,而不是創建並行線程,這使得如果pthread_mutex_t將實際的push和pop正常工作我懷疑。

線程安全的隊列

#include <queue> 
#include <pthread.h> 

class ts_queue 
{ 

private: 

    std::queue<unsigned char*> _queue_; 
    pthread_mutex_t mutex; 
    pthread_cond_t cond; 

public: 

    ts_queue() 
    { 
     pthread_mutex_init(&mutex, NULL); 
     pthread_cond_init(&cond, NULL); 
    } 

    void push(unsigned char* data) 
    { 
     pthread_mutex_lock(&mutex); 

     _queue_.push(data); 

     pthread_cond_signal(&cond); 
     pthread_mutex_unlock(&mutex); 
    } 

    void pop(unsigned char** popped_data) 
    { 
     pthread_mutex_lock(&mutex); 

     while (_queue_.empty() == true) 
     { 
      pthread_cond_wait(&cond, &mutex); 
     } 

     *popped_data = _queue_.front(); 
     _queue_.pop(); 

     pthread_mutex_unlock(&mutex); 
    } 
}; 

消費者測試:

void *consumer_thread(void *arguments) 
{ 
    ts_queue *tsq = static_cast<ts_queue*>(arguments); 

    while (true) 
    { 
     unsigned char* data = NULL; 

     tsq->pop(&data); 

     if (data != NULL) 
     { 
      // Eureka! Received from the other thread!!! 
      // Delete it so memory keeps free. 
      // NOTE: In the real scenario for which I need 
      // this class, the data received are bitmap pixels 
      // and at this point it would be processed 
      delete[] data; 
     } 
    } 

    return 0; 
} 

生產者TEST:

void main() 
{ 
    ts_queue tsq; 

    // Create the consumer 
    pthread_t consumer; 
    pthread_create(&consumer, NULL, consumer_thread, &tsq)); 

    // Start producing 
    while(true) 
    { 
     // Push data. 
     // Expected behaviour: memory should never run out, as the 
     // consumer should receive the data and delete it. 
     // NOTE: test_data in the real purpose scenario for which I 
     // need this class would hold bitmap pixels, so it's meant to 
     // hold binary data and not a string 

     unsigned char* test_data = new unsigned char [8192]; 
     tsq.push(test_data); 
    } 

    return 0; 
} 

回答

1

怎麼辦喲你知道消費者從來沒有收到數據嗎?當我嘗試你的程序時,我得到了一個分段錯誤,GDB告訴我消費者確實得到了一個指針,但它是無效的。

我相信你的問題是,你有_queue_部件上的數據競爭。 push()電話_queue_.push(data)(上_queue_寫),同時保持push_mutexpop()電話_queue_.front()(上_queue_讀)和_queue_.pop()(上_queue_另一個寫)同時舉行pop_mutex,但push()pop()可發生在同一時間,導致這兩個線程是同時寫作(和閱讀)_queue_,這是一個經典的數據競賽。