2014-02-13 109 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_,这是一个经典的数据竞赛。